aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2008-11-27 11:27:59 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2008-11-27 11:27:59 +0000
commitcb5c4b10ba7c6d9f83b961c24be8f766ea6156c0 (patch)
treeb42b5149fd6de96214266e5ed4d6e0b09734ce83
parent6974bd9e7543a0fc0afbc9de84f03ee27636b6f2 (diff)
Notes
-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
-rw-r--r--libexec/rtld-elf/Symbol.map2
-rw-r--r--libexec/rtld-elf/rtld.c2
-rw-r--r--libexec/rtld-elf/rtld_lock.c16
-rw-r--r--libexec/rtld-elf/rtld_lock.h2
7 files changed, 46 insertions, 1 deletions
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 6e8bfcefabd7..2e643134d4fb 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 39ba141a3308..eac3f1a1396a 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 713e0b5f8d1e..e16f884711e3 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) {
diff --git a/libexec/rtld-elf/Symbol.map b/libexec/rtld-elf/Symbol.map
index 325362c8ad6e..20f8d60f3611 100644
--- a/libexec/rtld-elf/Symbol.map
+++ b/libexec/rtld-elf/Symbol.map
@@ -21,4 +21,6 @@ FBSDprivate_1.0 {
_rtld_thread_init;
_rtld_allocate_tls;
_rtld_free_tls;
+ _rtld_atfork_pre;
+ _rtld_atfork_post;
};
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 144ea6c76c63..f67093ab0099 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -206,6 +206,8 @@ static func_ptr_type exports[] = {
(func_ptr_type) &_rtld_allocate_tls,
(func_ptr_type) &_rtld_free_tls,
(func_ptr_type) &dl_iterate_phdr,
+ (func_ptr_type) &_rtld_atfork_pre,
+ (func_ptr_type) &_rtld_atfork_post,
NULL
};
diff --git a/libexec/rtld-elf/rtld_lock.c b/libexec/rtld-elf/rtld_lock.c
index 5bb891a2ae82..bf4caf71176b 100644
--- a/libexec/rtld-elf/rtld_lock.c
+++ b/libexec/rtld-elf/rtld_lock.c
@@ -316,3 +316,19 @@ _rtld_thread_init(struct RtldLockInfo *pli)
thread_mask_set(flags);
dbg("_rtld_thread_init: done");
}
+
+void
+_rtld_atfork_pre(int *locks)
+{
+
+ locks[2] = wlock_acquire(rtld_phdr_lock);
+ locks[0] = rlock_acquire(rtld_bind_lock);
+}
+
+void
+_rtld_atfork_post(int *locks)
+{
+
+ rlock_release(rtld_bind_lock, locks[0]);
+ wlock_release(rtld_phdr_lock, locks[2]);
+}
diff --git a/libexec/rtld-elf/rtld_lock.h b/libexec/rtld-elf/rtld_lock.h
index 2e3f95422720..4c5d8541b3ea 100644
--- a/libexec/rtld-elf/rtld_lock.h
+++ b/libexec/rtld-elf/rtld_lock.h
@@ -44,6 +44,8 @@ struct RtldLockInfo
};
extern void _rtld_thread_init(struct RtldLockInfo *);
+extern void _rtld_atfork_pre(int *);
+extern void _rtld_atfork_post(int *);
#ifdef IN_RTLD