Detect and allow thread id reuse

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Detect and allow thread id reuse

Kevin Buettner
I've committed the patch below.  In a program which rapidly creates
threads which in turn rapidly exit, it is possible for NPTL to reuse a
recently exited thread id for a newly created thread.  RDA can fail to
detect this thread reuse.  One particularly bad consequence is that
RDA will fail to the new thread.

The patch below allows for thread id reuse by comparing the lwp
ids.  While this will work well for NPTL, it might possibly not
work for other thread implementations.  Note that the TID_MAY_BE_REUSED
should be moved into the configury at some point to accommodate other
threading implementations.

Kevin

2011-11-30  Kevin Buettner  <[hidden email]>

        * thread-db.c (TID_MAY_BE_REUSED): Define.
        (find_new_threads_callback): Detect thread id reuse.

Index: thread-db.c
===================================================================
RCS file: /cvs/src/src/rda/unix/thread-db.c,v
retrieving revision 1.20
diff -u -p -r1.20 thread-db.c
--- thread-db.c 1 Dec 2009 00:27:09 -0000 1.20
+++ thread-db.c 30 Nov 2011 23:05:49 -0000
@@ -49,6 +49,7 @@
 int thread_db_noisy = 0;
 
 #define ALWAYS_UPDATE_THREAD_LIST 0
+#define TID_MAY_BE_REUSED 1
 
 /*
  * A tiny local symbol table.
@@ -1426,11 +1427,25 @@ find_new_threads_callback (const td_thrh
 
   /* Enter the thread into a local list
      (unless it is TD_THR_UNKNOWN, which means its defunct). */
-  if ((thread = thread_list_lookup_by_tid (ti.ti_tid)) == NULL)
+  if ((thread = thread_list_lookup_by_tid (ti.ti_tid)) == NULL
+#if TID_MAY_BE_REUSED
+      || thread->ti.ti_lid != ti.ti_lid
+#endif
+      )
     {
       if (ti.ti_state != TD_THR_UNKNOWN)
  {
-  thread = add_thread_to_list (&ti);
+  if (thread)
+    {
+      /* Thread is being reused.  What has happened here is that
+         one thread has died and another was created using the
+ same thread identifier.  */
+      if (thread_db_noisy)
+ fprintf (stderr, "(thread deletion / reuse: %s)\n", thread_debug_name (thread));
+      thread->ti = ti;
+    }
+  else
+    thread = add_thread_to_list (&ti);
 
   if (thread_db_noisy)
     fprintf (stderr, "(new thread %s)\n", thread_debug_name
     (thread));