summaryrefslogtreecommitdiffstats
path: root/libexec
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 /libexec
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 'libexec')
-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
4 files changed, 22 insertions, 0 deletions
diff --git a/libexec/rtld-elf/Symbol.map b/libexec/rtld-elf/Symbol.map
index 325362c..20f8d60 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 144ea6c..f67093a 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 5bb891a..bf4caf7 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 2e3f954..4c5d854 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
OpenPOWER on IntegriCloud