diff options
author | kib <kib@FreeBSD.org> | 2014-06-07 02:45:24 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2014-06-07 02:45:24 +0000 |
commit | 8d9dc2de3a37d5f757fffb376a780d5081675f2e (patch) | |
tree | 747c00fc9e7b43e6077655fb1d4c318340f89b0e /lib | |
parent | 218f93e5f8ff4d66b5b39b99db1d741e7067e773 (diff) | |
download | FreeBSD-src-8d9dc2de3a37d5f757fffb376a780d5081675f2e.zip FreeBSD-src-8d9dc2de3a37d5f757fffb376a780d5081675f2e.tar.gz |
MFC r266609:
Change the _rtld_atfork() to lock the bind lock in write mode.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libthr/thread/thr_fork.c | 13 | ||||
-rw-r--r-- | lib/libthr/thread/thr_rtld.c | 21 |
2 files changed, 30 insertions, 4 deletions
diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c index c26541e..fc87688 100644 --- a/lib/libthr/thread/thr_fork.c +++ b/lib/libthr/thread/thr_fork.c @@ -57,6 +57,7 @@ * */ +#include <sys/syscall.h> #include "namespace.h" #include <errno.h> #include <link.h> @@ -174,8 +175,15 @@ _fork(void) was_threaded = 0; } - /* Fork a new process: */ - if ((ret = __sys_fork()) == 0) { + /* + * Fork a new process. + * There is no easy way to pre-resolve the __sys_fork symbol + * without performing the fork. Use the syscall(2) + * indirection, the syscall symbol is resolved in + * _thr_rtld_init() with side-effect free call. + */ + ret = syscall(SYS_fork); + if (ret == 0) { /* Child process */ errsave = errno; curthread->cancel_pending = 0; @@ -250,6 +258,5 @@ _fork(void) } errno = errsave; - /* Return the process ID: */ return (ret); } diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c index fd379d6..5d89988 100644 --- a/lib/libthr/thread/thr_rtld.c +++ b/lib/libthr/thread/thr_rtld.c @@ -32,10 +32,12 @@ */ #include <sys/cdefs.h> #include <sys/mman.h> +#include <sys/syscall.h> #include <link.h> #include <stdlib.h> #include <string.h> +#include "libc_private.h" #include "rtld_lock.h" #include "thr_private.h" @@ -207,7 +209,24 @@ _thr_rtld_init(void) li.thread_set_flag = _thr_rtld_set_flag; li.thread_clr_flag = _thr_rtld_clr_flag; li.at_fork = NULL; - + + /* + * Preresolve the symbols needed for the fork interposer. We + * call _rtld_atfork_pre() and _rtld_atfork_post() with NULL + * argument to indicate that no actual locking inside the + * functions should happen. Neither rtld compat locks nor + * libthr rtld locks cannot work there: + * - compat locks do not handle the case of two locks taken + * in write mode (the signal mask for the thread is corrupted); + * - libthr locks would work, but locked rtld_bind_lock prevents + * symbol resolution for _rtld_atfork_post. + */ + _rtld_atfork_pre(NULL); + _rtld_atfork_post(NULL); + _malloc_prefork(); + _malloc_postfork(); + syscall(SYS_getpid); + /* mask signals, also force to resolve __sys_sigprocmask PLT */ _thr_signal_block(curthread); _rtld_thread_init(&li); |