From owner-freebsd-bugs Wed Aug 28 10:20:17 2002 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 0894F37B400 for ; Wed, 28 Aug 2002 10:20:05 -0700 (PDT) Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id AC7D543E42 for ; Wed, 28 Aug 2002 10:20:04 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.4/8.12.4) with ESMTP id g7SHK4JU015630 for ; Wed, 28 Aug 2002 10:20:04 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.4/8.12.4/Submit) id g7SHK4xA015629; Wed, 28 Aug 2002 10:20:04 -0700 (PDT) Date: Wed, 28 Aug 2002 10:20:04 -0700 (PDT) Message-Id: <200208281720.g7SHK4xA015629@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Daniel Eischen Subject: Re: bin/42100: libc_r: accept(2) can't handle descriptor being closed/shutdown Reply-To: Daniel Eischen Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org The following reply was made to PR bin/42100; it has been noted by GNATS. From: Daniel Eischen To: archie@packetdesign.com Cc: Subject: Re: bin/42100: libc_r: accept(2) can't handle descriptor being closed/shutdown Date: Wed, 28 Aug 2002 10:08:40 -0400 I hacked up your program a bit and it looks like the kernel isn't doing the right thing for accept() on a closed file descriptor. If you take a look at lib/libc_r/uthread_accept.c, you'll see that it loops: while ((ret = __sys_accept(fd, name, namelen)) < 0) { /* Check if the socket is to block: */ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { /* Save the socket file descriptor: */ curthread->data.fd.fd = fd; curthread->data.fd.fname = __FILE__; curthread->data.fd.branch = __LINE__; [...] waiting for errno to be something other than EWOULDBLOCK or EAGAIN. So I modified your test program to mimic what libc_r was doing. The kernel seems to ignore the fact that the file is closed and always returns EAGAIN. I would expect EBADF or something. -- Dan Eischen /* Set to "1" to abort on signal, or "0" for thread-based delayed abort */ #ifndef SIGNAL_TEST #define SIGNAL_TEST 1 #endif #ifdef __linux__ #define _XOPEN_SOURCE 600 #define _GNU_SOURCE 1 #define _BSD_SOURCE 1 #define _ISOC99_SOURCE 1 #endif #include #define accept __sys_accept #include #undef accept #include #include #include #define poll __sys_poll #include #undef poll #include #include #include #include #include #include #include #include #if SIGNAL_TEST static void signal_handler(int sig); #else #include static void *thread_entry(void *arg); static pthread_t tid; #endif static int sock; int main(int ac, char **av) { struct sockaddr_in sin; socklen_t slen; struct pollfd fds; int flags; int ret; /* Create socket */ if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) err(1, "socket"); memset(&sin, 0, sizeof(sin)); #ifndef __linux__ sin.sin_len = sizeof(sin); #endif sin.sin_family = AF_INET; if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) err(1, "socket"); slen = sizeof(sin); if (listen(sock, 10) == -1) err(1, "listen"); /* Set non-blocking. */ if ((flags = fcntl(sock, F_GETFL, 0) < 0)) err(1, "fcntl"); flags |= O_NONBLOCK; if (fcntl(sock, F_SETFL, flags) < 0) err(1, "fcntl"); #if SIGNAL_TEST /* Register signal handler */ signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); #else /* Spawn thread */ if ((errno = pthread_create(&tid, NULL, thread_entry, NULL)) != 0) err(1, "pthread_create"); #endif /* Listen for connections on socket */ printf("main: waiting for connection...\n"); while (((ret = __sys_accept(sock, (struct sockaddr *)&sin, &slen)) < 0) && (errno == EWOULDBLOCK || errno == EAGAIN)) { printf("accept returned %d, errno %d\n", ret, errno); fds.events = POLLRDNORM | POLLERR | POLLHUP; fds.fd = sock; __sys_poll(&fds, 1, 2000); } if (ret < 0) err(1, "main: accept"); printf("main: got connection?\n"); return (0); } #if SIGNAL_TEST static void signal_handler(int sig) #else static void * thread_entry(void *arg) #endif { #if SIGNAL_TEST printf("%s: rec'd signal %d...\n", __FUNCTION__, sig); #else printf("%s: sleeping 2 seconds...\n", __FUNCTION__); sleep(2); #endif srandom(getpid() ^ time(NULL)); if ((random() & 0x00400000) != 0) { printf("%s: shutdown()'ing socket...\n", __FUNCTION__); if (shutdown(sock, SHUT_RDWR) == -1) err(1, "thread: shutdown"); } else { printf("%s: close()'ing socket...\n", __FUNCTION__); if (close(sock) == -1) err(1, "thread: shutdown"); } #if !SIGNAL_TEST return (NULL); #endif } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message