Michael Roth wrote: > >STDIO is one of the major areas of code that is definitely not > >async signal safe. Consider Thread A doing something like > >fwrite(stderr, "Foo\n"), while another thread forks, and then > >its child also does an fwrite(stderr, "Foo\n"). Given that > >every stdio function will lock/unlock a mutex, you easily get > >this sequence of events: > > > >1. Thread A: lock(stderr) > >2. Thread A: write(stderr, "foo\n"); > >3. Thread B: fork() -> Process B1 > >4. Thread A: unlock(stderr) > >5. Process B1: lock(stderr) > > > >When the child process is started at step 3, the FILE *stderr > >object will be locked by thread A. When Thread A does the > >unlock in step 4, it has no effect on Process B1. So process > >B1 hangs forever in step 5. > > Ahh, thanks for the example. I missed that these issues were > specifically WRT to code that was fork()'d from a multi-threaded > application. Seemed pretty scary otherwise :)
The pthread_atfork() mechanism, or equivalent in libc, should be sorting out those stdio locks, but I don't know for sure what Glibc does. I do know it traverses a stdio list on fork() though: http://sourceware.org/bugzilla/show_bug.cgi?id=4737#c4 Which is why Glibc's fork() is not async-signal-safe even though it's supposed to be. stdio in a fork() child is historical unix stuff; I expect there are quite a lot of old applications that use stdio in a child process. Not multi-threaded applications, but they can link to multi-threaded libraries these without knowing. Still there are bugs around (like Glibc's fork() not being async-signal-safe). It pays to be cautious. -- Jamie