When creating a child thread, initially set its os_state.threadgroup
to have the same value as the parent.  This avoids exit races leading
to hangs and strange behaviour in heavily multithreaded apps, in the
situation where threads are rapidly being created, and at the same
time an existing thread does sys_exit_group so as to terminate the
entire process.  Thanks to Konstantin S for chasing this down to a
small test case.  Fixes #226116.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11053 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_syswrap/syswrap-arm-linux.c b/coregrind/m_syswrap/syswrap-arm-linux.c
index b08da00..db81ac1 100644
--- a/coregrind/m_syswrap/syswrap-arm-linux.c
+++ b/coregrind/m_syswrap/syswrap-arm-linux.c
@@ -201,6 +201,17 @@
    ctst->sig_mask = ptst->sig_mask;
    ctst->tmp_sig_mask = ptst->sig_mask;
 
+   /* Start the child with its threadgroup being the same as the
+      parent's.  This is so that any exit_group calls that happen
+      after the child is created but before it sets its
+      os_state.threadgroup field for real (in thread_wrapper in
+      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
+      a race condition in which the thread is unkillable (via
+      exit_group) because its threadgroup is not set.  The race window
+      is probably only a few hundred or a few thousand cycles long.
+      See #226116. */
+   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
+
    seg = VG_(am_find_nsegment)((Addr)sp);
    if (seg && seg->kind != SkResvn) {
       ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);