From: Julian Seward Date: Mon, 14 Feb 2011 10:57:15 +0000 (+0000) Subject: Merge from trunk, r11525 (hg: Don't assert in the child after a X-Git-Tag: svn/VALGRIND_3_6_1~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb8f7f92ecb4285471c63c3393e7248c22483b29;p=thirdparty%2Fvalgrind.git Merge from trunk, r11525 (hg: Don't assert in the child after a threaded program does fork()) git-svn-id: svn://svn.valgrind.org/valgrind/branches/VALGRIND_3_6_BRANCH@11552 --- diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index 1be4f1382b..6af1a73351 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -52,6 +52,7 @@ #include "pub_tool_debuginfo.h" // VG_(find_seginfo), VG_(seginfo_soname) #include "pub_tool_redir.h" // sonames for the dynamic linkers #include "pub_tool_vki.h" // VKI_PAGE_SIZE +#include "pub_tool_libcproc.h" // VG_(atfork) #include "hg_basics.h" #include "hg_wordset.h" @@ -1679,6 +1680,8 @@ void evh__pre_thread_ll_exit ( ThreadId quit_tid ) - tell libhb the thread is gone - clear the map_threads entry, in order that the Valgrind core can re-use it. */ + /* Cleanup actions (next 5 lines) copied in evh__atfork_child; keep + in sync. */ tl_assert(thr_q->hbthr); libhb_async_exit(thr_q->hbthr); tl_assert(thr_q->coretid == quit_tid); @@ -1689,6 +1692,35 @@ void evh__pre_thread_ll_exit ( ThreadId quit_tid ) all__sanity_check("evh__pre_thread_ll_exit-post"); } +/* This is called immediately after fork, for the child only. 'tid' + is the only surviving thread (as per POSIX rules on fork() in + threaded programs), so we have to clean up map_threads to remove + entries for any other threads. */ +static +void evh__atfork_child ( ThreadId tid ) +{ + UInt i; + Thread* thr; + /* Slot 0 should never be used. */ + thr = map_threads_maybe_lookup( 0/*INVALID*/ ); + tl_assert(!thr); + /* Clean up all other slots except 'tid'. */ + for (i = 1; i < VG_N_THREADS; i++) { + if (i == tid) + continue; + thr = map_threads_maybe_lookup(i); + if (!thr) + continue; + /* Cleanup actions (next 5 lines) copied from end of + evh__pre_thread_ll_exit; keep in sync. */ + tl_assert(thr->hbthr); + libhb_async_exit(thr->hbthr); + tl_assert(thr->coretid == i); + thr->coretid = VG_INVALID_THREADID; + map_threads_delete(i); + } +} + static void evh__HG_PTHREAD_JOIN_POST ( ThreadId stay_tid, Thread* quit_thr ) @@ -4916,6 +4948,8 @@ static void hg_pre_clo_init ( void ) hg_mallocmeta_table = VG_(HT_construct)( "hg_malloc_metadata_table" ); + // add a callback to clean up on (threaded) fork. + VG_(atfork)(NULL/*pre*/, NULL/*parent*/, evh__atfork_child/*child*/); } VG_DETERMINE_INTERFACE_VERSION(hg_pre_clo_init)