[patch] Fix for PR gdb/10757

Paul Pluzhnikov ppluzhnikov@google.com
Tue Oct 27 21:38:00 GMT 2009


On Mon, Oct 26, 2009 at 2:25 PM, Paul Pluzhnikov <ppluzhnikov@google.com> wrote:

> I'll commit attached patch tomorrow if there are no further comments.

So committed.

> A similar patch is required for gdbserver as well.

Attached.

Thanks,
-- 
Paul Pluzhnikov

2009-10-27  Paul Pluzhnikov  <ppluzhnikov@google.com>

	PR gdb/10757
	* thread-db.c (attach_thread): New function.
	(maybe_attach_thread): Return success/failure.
	(find_new_threads_callback): Adjust.
	(thread_db_find_new_threads): Loop until no new threads.
-------------- next part --------------
Index: gdbserver/thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/thread-db.c,v
retrieving revision 1.24
diff -u -p -u -r1.24 thread-db.c
--- gdbserver/thread-db.c	9 Oct 2009 00:31:01 -0000	1.24
+++ gdbserver/thread-db.c	27 Oct 2009 21:12:12 -0000
@@ -297,16 +297,13 @@ find_one_thread (ptid_t ptid)
   return 1;
 }
 
-static void
-maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
+/* Attach a thread.  Return true on success.  */
+
+static int
+attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
 {
-  td_err_e err;
   struct lwp_info *lwp;
 
-  lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
-  if (lwp != NULL)
-    return;
-
   if (debug_threads)
     fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
 	     ti_p->ti_tid, ti_p->ti_lid);
@@ -316,7 +313,7 @@ maybe_attach_thread (const td_thrhandle_
     {
       warning ("Could not attach to thread %ld (LWP %d)\n",
 	       ti_p->ti_tid, ti_p->ti_lid);
-      return;
+      return 0;
     }
 
   lwp->thread_known = 1;
@@ -324,12 +321,39 @@ maybe_attach_thread (const td_thrhandle_
 
   if (thread_db_use_events)
     {
+      td_err_e err;
       struct thread_db *thread_db = current_process ()->private->thread_db;
+
       err = thread_db->td_thr_event_enable_p (th_p, 1);
       if (err != TD_OK)
 	error ("Cannot enable thread event reporting for %d: %s",
 	       ti_p->ti_lid, thread_db_err_str (err));
     }
+
+  return 1;
+}
+
+/* Attach thread if we haven't seen it yet.
+   Increment *COUNTER if we have attached a new thread.
+   Return false on failure.  */
+
+static int
+maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p,
+		     int *counter)
+{
+  struct lwp_info *lwp;
+
+  lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
+  if (lwp != NULL)
+    return 1;
+
+  if (!attach_thread (th_p, ti_p))
+    return 0;
+
+  if (counter != NULL)
+    *counter += 1;
+
+  return 1;
 }
 
 static int
@@ -347,7 +371,12 @@ find_new_threads_callback (const td_thrh
   if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
     return 0;
 
-  maybe_attach_thread (th_p, &ti);
+  if (!maybe_attach_thread (th_p, &ti, (int *) data))
+    {
+      /* Terminate iteration early: we might be looking at stale data in
+	 the inferior.  The thread_db_find_new_threads will retry.  */
+      return 1;
+    }
 
   return 0;
 }
@@ -358,6 +387,7 @@ thread_db_find_new_threads (void)
   td_err_e err;
   ptid_t ptid = ((struct inferior_list_entry *) current_inferior)->id;
   struct thread_db *thread_db = current_process ()->private->thread_db;
+  int loop, iteration;
 
   /* This function is only called when we first initialize thread_db.
      First locate the initial thread.  If it is not ready for
@@ -365,11 +395,30 @@ thread_db_find_new_threads (void)
   if (find_one_thread (ptid) == 0)
     return;
 
-  /* Iterate over all user-space threads to discover new threads.  */
-  err = thread_db->td_ta_thr_iter_p (thread_db->thread_agent,
-				     find_new_threads_callback, NULL,
-				     TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
-				     TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
+  /* Require 4 successive iterations which do not find any new threads.
+     The 4 is a heuristic: there is an inherent race here, and I have
+     seen that 2 iterations in a row are not always sufficient to
+     "capture" all threads.  */
+  for (loop = 0, iteration = 0; loop < 4; ++loop, ++iteration)
+    {
+      int new_thread_count = 0;
+
+      /* Iterate over all user-space threads to discover new threads.  */
+      err = thread_db->td_ta_thr_iter_p (thread_db->thread_agent,
+					 find_new_threads_callback,
+					 &new_thread_count,
+					 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
+					 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
+      if (debug_threads)
+	fprintf (stderr, "Found %d threads in iteration %d.\n",
+		 new_thread_count, iteration);
+
+      if (new_thread_count != 0)
+	{
+	  /* Found new threads.  Restart iteration from beginning.  */
+	  loop = -1;
+	}
+    }
   if (err != TD_OK)
     error ("Cannot find new threads: %s", thread_db_err_str (err));
 }


More information about the Gdb-patches mailing list