From: Nicholas Nethercote Date: Sun, 13 Mar 2005 04:43:10 +0000 (+0000) Subject: When a multi-threaded program forks(), only the thread actually X-Git-Tag: svn/VALGRIND_3_0_0~995 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f55e0fc12e896f4a4bb988559e8eba90df9c13de;p=thirdparty%2Fvalgrind.git When a multi-threaded program forks(), only the thread actually calling fork() appears in the child. The child Valgrind will inherit a VG_(threads) array which still describes the other threads. The code in vg_scheduler:sched_fork_cleanup is responsible for doing this, but it was only "killing" the other threads by setting their statuses to VgTs_Empty. This was causing confusion if the child later created other threads and found partially initialized threads structures. This change makes sched_fork_cleanup fully reinitialize the other thread slots in VG_(threads). MERGED FROM CVS HEAD git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3323 --- diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index bd8124d0ac..9a3cfb15d1 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -570,8 +570,23 @@ void mostly_clear_thread_record ( ThreadId tid ) VG_(threads)[tid].sched_jmpbuf_valid = False; } -/* Called in the child after fork. Presumably the parent was running, - so we now we're running. */ +/* + Called in the child after fork. If the parent has multiple + threads, then we've inhereted a VG_(threads) array describing them, + but only the thread which called fork() is actually alive in the + child. This functions needs to clean up all those other thread + structures. + + Whichever tid in the parent which called fork() becomes the + master_tid in the child. That's because the only living slot in + VG_(threads) in the child after fork is VG_(threads)[tid], and it + would be too hard to try to re-number the thread and relocate the + thread state down to VG_(threads)[1]. + + This function also needs to reinitialize the run_sema, since + otherwise we may end up sharing its state with the parent, which + would be deeply confusing. +*/ static void sched_fork_cleanup(ThreadId me) { ThreadId tid; @@ -584,8 +599,10 @@ static void sched_fork_cleanup(ThreadId me) /* clear out all the unused thread slots */ for (tid = 1; tid < VG_N_THREADS; tid++) { - if (tid != me) + if (tid != me) { + mostly_clear_thread_record(tid); VG_(threads)[tid].status = VgTs_Empty; + } } /* re-init and take the sema */