diff options
author | kib <kib@FreeBSD.org> | 2008-11-27 11:27:59 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2008-11-27 11:27:59 +0000 |
commit | b683fcf69217f7195e73b2f05d608c952101f47a (patch) | |
tree | b42b5149fd6de96214266e5ed4d6e0b09734ce83 /lib/libthr/thread/thr_fork.c | |
parent | 9ef49d8b6f56c91c360dacd78c3cab2300da33fb (diff) | |
download | FreeBSD-src-b683fcf69217f7195e73b2f05d608c952101f47a.zip FreeBSD-src-b683fcf69217f7195e73b2f05d608c952101f47a.tar.gz |
Add two rtld exported symbols, _rtld_atfork_pre and _rtld_atfork_post.
Threading library calls _pre before the fork, allowing the rtld to
lock itself to ensure that other threads of the process are out of
dynamic linker. _post releases the locks.
This allows the rtld to have consistent state in the child. Although
child may legitimately call only async-safe functions, the call may
need plt relocation resolution, and this requires working rtld.
Reported and debugging help by: rink
Reviewed by: kan, davidxu
MFC after: 1 month (anyway, not before 7.1 is out)
Diffstat (limited to 'lib/libthr/thread/thr_fork.c')
-rw-r--r-- | lib/libthr/thread/thr_fork.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c index 713e0b5..e16f884 100644 --- a/lib/libthr/thread/thr_fork.c +++ b/lib/libthr/thread/thr_fork.c @@ -67,6 +67,7 @@ #include "un-namespace.h" #include "libc_private.h" +#include "rtld_lock.h" #include "thr_private.h" __weak_reference(_pthread_atfork, pthread_atfork); @@ -105,6 +106,7 @@ _fork(void) pid_t ret; int errsave; int unlock_malloc; + int rtld_locks[16]; if (!_thr_is_inited()) return (__sys_fork()); @@ -127,6 +129,7 @@ _fork(void) if (_thr_isthreaded() != 0) { unlock_malloc = 1; _malloc_prefork(); + _rtld_atfork_pre(rtld_locks); } else { unlock_malloc = 0; } @@ -167,6 +170,10 @@ _fork(void) /* Ready to continue, unblock signals. */ _thr_signal_unblock(curthread); + if (unlock_malloc) { + _rtld_atfork_post(rtld_locks); + } + /* Run down atfork child handlers. */ TAILQ_FOREACH(af, &_thr_atfork_list, qe) { if (af->child != NULL) @@ -179,8 +186,10 @@ _fork(void) /* Ready to continue, unblock signals. */ _thr_signal_unblock(curthread); - if (unlock_malloc) + if (unlock_malloc) { + _rtld_atfork_post(rtld_locks); _malloc_postfork(); + } /* Run down atfork parent handlers. */ TAILQ_FOREACH(af, &_thr_atfork_list, qe) { |