|
From: <sv...@va...> - 2011-02-09 10:34:10
|
Author: sewardj
Date: 2011-02-09 10:34:00 +0000 (Wed, 09 Feb 2011)
New Revision: 11525
Log:
Don't assert in the child after a threaded program does fork().
Fixes #255355 (helgrind part).
Modified:
trunk/helgrind/hg_main.c
Modified: trunk/helgrind/hg_main.c
===================================================================
--- trunk/helgrind/hg_main.c 2011-02-04 20:50:58 UTC (rev 11524)
+++ trunk/helgrind/hg_main.c 2011-02-09 10:34:00 UTC (rev 11525)
@@ -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 @@
- 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,7 +1692,36 @@
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 @@
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)
|