summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_fork.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2014-05-24 10:23:06 +0000
committerkib <kib@FreeBSD.org>2014-05-24 10:23:06 +0000
commit1b73f3761fc6bb166b9011b59b584f5273f9c0ed (patch)
tree013989eded475e9be57868fa60cc2a1b7133ff82 /lib/libthr/thread/thr_fork.c
parent7d2507a09db7441bf0ec5a2b33729f964a99d074 (diff)
downloadFreeBSD-src-1b73f3761fc6bb166b9011b59b584f5273f9c0ed.zip
FreeBSD-src-1b73f3761fc6bb166b9011b59b584f5273f9c0ed.tar.gz
Right now, the rtld prefork hook locks the rtld bind lock in the read
mode. This allows the binder to be functional in the child after the fork (assuming no lazy loading of a filter is needed), but other rtld services which require write lock on rtld_bind_lock cause deadlock, if called by child. Change the _rtld_atfork() to lock the bind lock in write mode, making the rtld fully functional after the fork. Pre-resolve the symbols which are called by the libthr' fork() interposer, since dynamic resolution causes deadlock due to the rtld_bind_lock already owned in the write mode. Reported and tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
Diffstat (limited to 'lib/libthr/thread/thr_fork.c')
-rw-r--r--lib/libthr/thread/thr_fork.c13
1 files changed, 10 insertions, 3 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);
}
OpenPOWER on IntegriCloud