Taylor R Campbell
2014-06-23 14:09:04 UTC
Pthread_atfork(3) says that no pthread_* routines may be used in the
child handler. But this completely defeats the purpose of
pthread_atfork. As the POSIX rationale section explains,
`The expected usage is that the prepare handler acquires all mutex
locks and the other two fork handlers release them.'
http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html
There is a long comment in src/lib/libc/gen/pthread_atfork.c
explaining why the child does mutex_init instead of mutex_unlock: if
the spin lock inside a mutex is held by another thread, then trying to
unlock the mutex in the child will wait forever because the other
thread won't be there in the child.
That comment was written by nathanw@ in 2003 and is no longer accurate
about the state of affairs, since libpthread has been basically
completely rewritten and there is no internal spin lock involved. I
believe it is still safe to use mutex_init, but that doesn't help
portable code.
So, is it safe now to use mutex_unlock?
Cursory examination of pthread_mutex.c suggests to me that it is, in
spite of the exhortation in the pthread_atfork(3) man page. But
because of that exhortation I'm not sure we really guarantee it to
work. It would be good if we made sure pthread_mutex_unlock reliably
works in a child handler, and documented the fact and stuck to it.
We already do use pthread_mutex_unlock in pthread_atfork child
handlers -- see, e.g., the arc4random(3) code. (We could plausibly
make the arc4random state thread-local to sidestep this issue, but
that's not true of other global databases.)
child handler. But this completely defeats the purpose of
pthread_atfork. As the POSIX rationale section explains,
`The expected usage is that the prepare handler acquires all mutex
locks and the other two fork handlers release them.'
http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html
There is a long comment in src/lib/libc/gen/pthread_atfork.c
explaining why the child does mutex_init instead of mutex_unlock: if
the spin lock inside a mutex is held by another thread, then trying to
unlock the mutex in the child will wait forever because the other
thread won't be there in the child.
That comment was written by nathanw@ in 2003 and is no longer accurate
about the state of affairs, since libpthread has been basically
completely rewritten and there is no internal spin lock involved. I
believe it is still safe to use mutex_init, but that doesn't help
portable code.
So, is it safe now to use mutex_unlock?
Cursory examination of pthread_mutex.c suggests to me that it is, in
spite of the exhortation in the pthread_atfork(3) man page. But
because of that exhortation I'm not sure we really guarantee it to
work. It would be good if we made sure pthread_mutex_unlock reliably
works in a child handler, and documented the fact and stuck to it.
We already do use pthread_mutex_unlock in pthread_atfork child
handlers -- see, e.g., the arc4random(3) code. (We could plausibly
make the arc4random state thread-local to sidestep this issue, but
that's not true of other global databases.)