summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2008-11-27 11:27:59 +0000
committerkib <kib@FreeBSD.org>2008-11-27 11:27:59 +0000
commitb683fcf69217f7195e73b2f05d608c952101f47a (patch)
treeb42b5149fd6de96214266e5ed4d6e0b09734ce83 /lib
parent9ef49d8b6f56c91c360dacd78c3cab2300da33fb (diff)
downloadFreeBSD-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')
-rw-r--r--lib/libc/gen/Symbol.map2
-rw-r--r--lib/libc/gen/dlfcn.c12
-rw-r--r--lib/libthr/thread/thr_fork.c11
3 files changed, 24 insertions, 1 deletions
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 6e8bfce..2e64313 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -432,6 +432,8 @@ FBSDprivate_1.0 {
_spinlock;
_spinlock_debug;
_spinunlock;
+ _rtld_atfork_pre;
+ _rtld_atfork_post;
_rtld_error; /* for private use */
_rtld_thread_init; /* for private use */
_err;
diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c
index 39ba141..eac3f1a 100644
--- a/lib/libc/gen/dlfcn.c
+++ b/lib/libc/gen/dlfcn.c
@@ -137,3 +137,15 @@ dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
_rtld_error(sorry);
return 0;
}
+
+#pragma weak _rtld_atfork_pre
+void
+_rtld_atfork_pre(int *locks)
+{
+}
+
+#pragma weak _rtld_atfork_post
+void
+_rtld_atfork_post(int *locks)
+{
+}
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) {
OpenPOWER on IntegriCloud