DRD: do not assert() upon fork(). Fixes the DRD part of #255355.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11520 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/drd/drd_main.c b/drd/drd_main.c
index e317857..ebf0845 100644
--- a/drd/drd_main.c
+++ b/drd/drd_main.c
@@ -627,6 +627,18 @@
    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.
 //
@@ -756,6 +768,8 @@
    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 909bb45..f85a5b0 100644
--- a/drd/drd_thread.c
+++ b/drd/drd_thread.c
@@ -504,6 +504,21 @@
    }
 }
 
+/** 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);
+      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 cb4853b..920df4a 100644
--- a/drd/drd_thread.h
+++ b/drd/drd_thread.h
@@ -136,6 +136,7 @@
 void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee);
 void DRD_(thread_delete)(const DrdThreadId tid);
 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);