]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
When a multi-threaded program forks(), only the thread actually
authorNicholas Nethercote <njn@valgrind.org>
Sun, 13 Mar 2005 04:43:10 +0000 (04:43 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Sun, 13 Mar 2005 04:43:10 +0000 (04:43 +0000)
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

coregrind/vg_scheduler.c

index bd8124d0ac694695d1a65cdfb1e31b7d5591c9fd..9a3cfb15d166d2f6742db8cf54cd7e871ef0d254 100644 (file)
@@ -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 */