From 4f9c86462788dab9351527cc6ad6db70adff6d22 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Mon, 14 Feb 2011 11:05:57 +0000 Subject: [PATCH] Merge from trunk, r11520 and r11532 (drd: don't assert in the child after threaded fork()) git-svn-id: svn://svn.valgrind.org/valgrind/branches/VALGRIND_3_6_BRANCH@11553 --- drd/drd_main.c | 14 ++++++++++++++ drd/drd_thread.c | 24 +++++++++++++++++++++--- drd/drd_thread.h | 3 ++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/drd/drd_main.c b/drd/drd_main.c index 953120b754..712ce4ce19 100644 --- a/drd/drd_main.c +++ b/drd/drd_main.c @@ -625,6 +625,18 @@ static void drd_thread_finished(ThreadId vg_tid) DRD_(thread_finished)(drd_tid); } +/* + * Called immediately after fork for the child process only. 'tid' is the + * only surviving thread in the child process. Cleans up thread state. + * See also http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html for a detailed discussion of using fork() in combination with mutexes. + */ +static +void drd__atfork_child(ThreadId tid) +{ + DRD_(drd_thread_atfork_child)(tid); +} + + // // Implementation of the tool interface. // @@ -754,6 +766,8 @@ void drd_pre_clo_init(void) VG_(track_pre_thread_ll_create) (drd_pre_thread_create); VG_(track_pre_thread_first_insn)(drd_post_thread_create); VG_(track_pre_thread_ll_exit) (drd_thread_finished); + VG_(atfork) (NULL/*pre*/, NULL/*parent*/, + drd__atfork_child/*child*/); // Other stuff. DRD_(register_malloc_wrappers)(drd_start_using_mem_w_ecu, diff --git a/drd/drd_thread.c b/drd/drd_thread.c index 909bb45a19..a31531ed9d 100644 --- a/drd/drd_thread.c +++ b/drd/drd_thread.c @@ -367,7 +367,7 @@ void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee) DRD_(thread_get_stack_max)(drd_joinee)); } DRD_(clientobj_delete_thread)(drd_joinee); - DRD_(thread_delete)(drd_joinee); + DRD_(thread_delete)(drd_joinee, False); } /** @@ -450,7 +450,7 @@ Int DRD_(thread_get_threads_on_alt_stack)(void) * Clean up thread-specific data structures. Call this just after * pthread_join(). */ -void DRD_(thread_delete)(const DrdThreadId tid) +void DRD_(thread_delete)(const DrdThreadId tid, const Bool detached) { Segment* sg; Segment* sg_prev; @@ -467,7 +467,10 @@ void DRD_(thread_delete)(const DrdThreadId tid) } DRD_(g_threadinfo)[tid].vg_thread_exists = False; DRD_(g_threadinfo)[tid].posix_thread_exists = False; - tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False); + if (detached) + DRD_(g_threadinfo)[tid].detached_posix_thread = False; + else + tl_assert(!DRD_(g_threadinfo)[tid].detached_posix_thread); DRD_(g_threadinfo)[tid].first = 0; DRD_(g_threadinfo)[tid].last = 0; @@ -504,6 +507,21 @@ void DRD_(thread_finished)(const DrdThreadId tid) } } +/** Called just after fork() in the child process. */ +void DRD_(drd_thread_atfork_child)(const DrdThreadId tid) +{ + unsigned i; + + for (i = 1; i < DRD_N_THREADS; i++) + { + if (i == tid) + continue; + if (DRD_(IsValidDrdThreadId(i))) + DRD_(thread_delete)(i, True); + tl_assert(!DRD_(IsValidDrdThreadId(i))); + } +} + /** Called just before pthread_cancel(). */ void DRD_(thread_pre_cancel)(const DrdThreadId tid) { diff --git a/drd/drd_thread.h b/drd/drd_thread.h index cb4853b01d..8d63467acf 100644 --- a/drd/drd_thread.h +++ b/drd/drd_thread.h @@ -134,8 +134,9 @@ DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator, const ThreadId vg_created); DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created); void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee); -void DRD_(thread_delete)(const DrdThreadId tid); +void DRD_(thread_delete)(const DrdThreadId tid, Bool detached); void DRD_(thread_finished)(const DrdThreadId tid); +void DRD_(drd_thread_atfork_child)(const DrdThreadId tid); void DRD_(thread_pre_cancel)(const DrdThreadId tid); void DRD_(thread_set_stack_startup)(const DrdThreadId tid, const Addr stack_startup); -- 2.47.2