misc/41331: Pthread library open sets O_NONBLOCK flag andcauses
unnecessary EAGAIN errors especially with /dev/stdout.
Dorr H. Clark
dclark at applmath.scu.edu
Mon May 5 20:40:32 PDT 2003
The following reply was made to PR misc/41331; it has been noted by GNATS.
From: "Dorr H. Clark" <dclark at applmath.scu.edu>
To: freebsd-gnats-submit at FreeBSD.org, alo at iki.fi
Cc:
Subject: Re: misc/41331: Pthread library open sets O_NONBLOCK flag and causes
unnecessary EAGAIN errors especially with /dev/stdout.
Date: Mon, 05 May 2003 20:37:20 -0700
42943 is a duplicate of 41331, or at best an extended symptom.
First of all, both 41331 and 42943 occur on purpose,
and this is not a regression introduced by some other change,
it is part of the original pthread code.
We believe that this behavior is a side effect of the FreeBSD
threads implementation, and that 41331 and 42943 are normal behavior.
These bugs can only plausibly be addressed by rearchitecting
the threads implementation, possibly in the context of 5.x.
In FreeBSD, the pthread implementation is as a user-level thread
package,
in other words, all threads execute in the context of a single process,
and the thread scheduler is hidden in the threaded version of libc.
As a side-effect of this implementation, when a blocking system call
is executed, the kernel only knows about the process, and
this results in all the threads being blocked.
To avoid blocking the entire thread group, the stdin, stdout and stderr
file descriptors are made non-blocking.
Note that while these two bugs were filed against the recent 4.x
releases,
there is nothing new in this area. The code governing this behavior
has 2.x and 3.x labels in the CVS tree.
In 41331, there is a test program, and as part of our investigation
we tried this program on both Solaris and Linux. Neither one exhibits
the 41331 behavior, however readers who are familiar with the threads
implementation will realize that these are three radically different
threads implementations, accounting for the discrepancy.
If the 41331 behavior is intolerable, there are two possible approaches,
either wait for a pthreads implementation on top of the kernel threads
in FreeBSD 5.0 or install the linuxthreads port, which simulates the
Linux
way of handling threads as separate processes.
NOTE: The following code excerpt is from 4.7-STABLE !
Here are two code snips which control this behavior.
code snip from libc_r/uthread/pthread_private.h :
/*
* Standard I/O file descriptors need special flag treatment since
* setting one to non-blocking does all on *BSD. Sigh. This array
* is used to store the initial flag settings.
*/
SCLASS int _pthread_stdio_flags[3];
code snip from uthread_fd.c :
/* Check if a stdio descriptor: */
if ((fd < 3) && (_pthread_stdio_flags[fd] !=
-1))
/*
* Use the stdio flags read by
* _pthread_init() to avoid
* mistaking the non-blocking
* flag that, when set on one
* stdio fd, is set on all stdio
* fds.
*/
entry->flags = _pthread_stdio_flags[fd];
/*
* Make the file descriptor non-blocking.
* This might fail if the device driver does
* not support non-blocking calls, or if the
* driver is naturally non-blocking.
*/
saved_errno = errno;
_thread_sys_fcntl(fd, F_SETFL,
entry->flags | O_NONBLOCK);
errno = saved_errno;
Rashmi Venkatesh, engineer
Dorr H. Clark, advisor
COEN 284 - Operating Systems Case Study
Santa Clara University,
Santa Clara CA.
More information about the freebsd-bugs
mailing list