From owner-freebsd-current Wed Sep 9 17:23:24 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id RAA16505 for freebsd-current-outgoing; Wed, 9 Sep 1998 17:23:24 -0700 (PDT) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from pcnet1.pcnet.com (pcnet1.pcnet.com [204.213.232.3]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id RAA16493 for ; Wed, 9 Sep 1998 17:23:10 -0700 (PDT) (envelope-from eischen@vigrid.com) Received: (from eischen@localhost) by pcnet1.pcnet.com (8.8.7/PCNet) id UAA19743; Wed, 9 Sep 1998 20:23:07 -0400 (EDT) Date: Wed, 9 Sep 1998 20:23:07 -0400 (EDT) From: Daniel Eischen Message-Id: <199809100023.UAA19743@pcnet1.pcnet.com> To: eischen@vigrid.com, tlambert@primenet.com Subject: Re: Thread Problems Cc: freebsd-current@FreeBSD.ORG, info@highwind.com Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG > > It does seem that the listen socket somehow became blocking, > > but it isn't apparent by looking at the code. Is a > > fcntl(fd, F_SETFL, O_NONBLOCK) sufficient to set a socket I should have said _thread_sys_fcntl(fd, F_SETFL, O_NONBLOCK) > > non-blocking across multiple accepts? > > No. > > You are getting confused here between the non-blocking flag on > the actual fd, and the non-blocking flag maintained in user space > threading to determine how a call should be multiplexed. No, I understand that :-) I've looked at and modified the threads library enough so that I understand that much anyways. > That is, if a socket is created via socket(3) (the threads library > socket(3) is a wrapper for socket(2)), the socket(2) socket will > be non-blocking, but the socket(3) socket will be "blocking" (that > is, a call to it will block the thread making the call until the > call can be completed successfully). > > This is the difference between "blocking the thread" and "blocking > the process". > > If a "blocking" call is made (i.e., a call on a "blocking" fd, from > the thread's perspective), then it will block. > > The socket option inheritance issue applies to the inheritance of > user space flags, as well, which I don't think the threads library > successfully wraps. Yes, fcntl is wrapped so that it ORs the users requested flags with O_NONBLOCK. If the program is setting the O_NONBLOCK then this will be saved and remembered in the threads file descriptor table. When the threads library sets the file to non-blocking it doesn't set the O_NONBLOCK flag in the file descriptor table. Look at the code: (from uthread_accept.c) /* Enter a loop to wait for a connection request: */ while ((ret = _thread_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: */ _thread_run->data.fd.fd = fd; _thread_run->data.fd.fname = __FILE__; _thread_run->data.fd.branch = __LINE__; /* Set the timeout: */ _thread_kern_set_timeout(NULL); /* Schedule the next thread: */ _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); /* Check if the wait was interrupted: */ if (errno == EINTR) { /* Return an error status: */ ret = -1; break; } } else { /* * Another error has occurred, so exit the * loop here: */ break; } } _thread_fd_table[fd]->flags should only have O_NONBLOCK set if the user application set it so. Regardless, the file was made non-blocking when it was created with socket(3). The code seems to do the right thing -- as long as the socket is still non-blocking. > If the server code expects the "non-blocking" flag, as set within > the context of a thread, so that the call will not result in a > threads context switch, to be non-blocking after derivation from > another socket where the flag was set, then this could be the problem. What do you mean by "derivation from another socket"? dup/dup2/fcntl? Aren't these suppose to preserve the O_NONBLOCK flag? The threads library preserves the user space flags, but if the O_NONBLOCK flag isn't set by the application, then it relies on the system call to preserve the flag. I tried to repeat the reported problem, but couldn't. I had one thread listening for client connections, a worker thread (printing a message once a second), and main. The thread listening for client connections would create a thread to handle the connection and go back to accepting more connections. I couldn't make it fail - the worker thread was always spewing out messages once a second. I even tried using fork to process each client request that came in - that worked also. It'd be nice to see a sample program that reproduced the problem. I can send info@highwind.com my test program if he wants to try to hack it up to demonstrate the problem. Dan Eischen eischen@vigrid.com To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message