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)
This commit is contained in:
parent
6974bd9e75
commit
cb5c4b10ba
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -21,4 +21,6 @@ FBSDprivate_1.0 {
|
||||
_rtld_thread_init;
|
||||
_rtld_allocate_tls;
|
||||
_rtld_free_tls;
|
||||
_rtld_atfork_pre;
|
||||
_rtld_atfork_post;
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user