svn commit: r185369 - in head: lib/libc/gen lib/libthr/thread libexec/rtld-elf

Konstantin Belousov kib at FreeBSD.org
Thu Nov 27 03:28:00 PST 2008


Author: kib
Date: Thu Nov 27 11:27:59 2008
New Revision: 185369
URL: http://svn.freebsd.org/changeset/base/185369

Log:
  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)

Modified:
  head/lib/libc/gen/Symbol.map
  head/lib/libc/gen/dlfcn.c
  head/lib/libthr/thread/thr_fork.c
  head/libexec/rtld-elf/Symbol.map
  head/libexec/rtld-elf/rtld.c
  head/libexec/rtld-elf/rtld_lock.c
  head/libexec/rtld-elf/rtld_lock.h

Modified: head/lib/libc/gen/Symbol.map
==============================================================================
--- head/lib/libc/gen/Symbol.map	Thu Nov 27 11:25:21 2008	(r185368)
+++ head/lib/libc/gen/Symbol.map	Thu Nov 27 11:27:59 2008	(r185369)
@@ -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;

Modified: head/lib/libc/gen/dlfcn.c
==============================================================================
--- head/lib/libc/gen/dlfcn.c	Thu Nov 27 11:25:21 2008	(r185368)
+++ head/lib/libc/gen/dlfcn.c	Thu Nov 27 11:27:59 2008	(r185369)
@@ -137,3 +137,15 @@ dl_iterate_phdr(int (*callback)(struct d
 	_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)
+{
+}

Modified: head/lib/libthr/thread/thr_fork.c
==============================================================================
--- head/lib/libthr/thread/thr_fork.c	Thu Nov 27 11:25:21 2008	(r185368)
+++ head/lib/libthr/thread/thr_fork.c	Thu Nov 27 11:27:59 2008	(r185369)
@@ -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) {

Modified: head/libexec/rtld-elf/Symbol.map
==============================================================================
--- head/libexec/rtld-elf/Symbol.map	Thu Nov 27 11:25:21 2008	(r185368)
+++ head/libexec/rtld-elf/Symbol.map	Thu Nov 27 11:27:59 2008	(r185369)
@@ -21,4 +21,6 @@ FBSDprivate_1.0 {
     _rtld_thread_init;
     _rtld_allocate_tls;
     _rtld_free_tls;
+    _rtld_atfork_pre;
+    _rtld_atfork_post;
 };

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c	Thu Nov 27 11:25:21 2008	(r185368)
+++ head/libexec/rtld-elf/rtld.c	Thu Nov 27 11:27:59 2008	(r185369)
@@ -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
 };
 

Modified: head/libexec/rtld-elf/rtld_lock.c
==============================================================================
--- head/libexec/rtld-elf/rtld_lock.c	Thu Nov 27 11:25:21 2008	(r185368)
+++ head/libexec/rtld-elf/rtld_lock.c	Thu Nov 27 11:27:59 2008	(r185369)
@@ -316,3 +316,19 @@ _rtld_thread_init(struct RtldLockInfo *p
 	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]);
+}

Modified: head/libexec/rtld-elf/rtld_lock.h
==============================================================================
--- head/libexec/rtld-elf/rtld_lock.h	Thu Nov 27 11:25:21 2008	(r185368)
+++ head/libexec/rtld-elf/rtld_lock.h	Thu Nov 27 11:27:59 2008	(r185369)
@@ -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
 


More information about the svn-src-all mailing list