From owner-svn-src-all@FreeBSD.ORG Thu Nov 27 11:28:00 2008 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8238F1065673; Thu, 27 Nov 2008 11:28:00 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6DD638FC19; Thu, 27 Nov 2008 11:28:00 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mARBS08p085866; Thu, 27 Nov 2008 11:28:00 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mARBS0Kw085859; Thu, 27 Nov 2008 11:28:00 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200811271128.mARBS0Kw085859@svn.freebsd.org> From: Konstantin Belousov Date: Thu, 27 Nov 2008 11:28:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r185369 - in head: lib/libc/gen lib/libthr/thread libexec/rtld-elf X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Nov 2008 11:28:00 -0000 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