Date: Wed, 9 Sep 1998 20:23:07 -0400 (EDT) From: Daniel Eischen <eischen@vigrid.com> To: eischen@vigrid.com, tlambert@primenet.com Cc: freebsd-current@FreeBSD.ORG, info@highwind.com Subject: Re: Thread Problems Message-ID: <199809100023.UAA19743@pcnet1.pcnet.com>
next in thread | raw e-mail | index | archive | help
> > 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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199809100023.UAA19743>
