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 /libexec | |
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 'libexec')
-rw-r--r-- | libexec/rtld-elf/Symbol.map | 2 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld.c | 2 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld_lock.c | 16 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld_lock.h | 2 |
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 |