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)); }