@@ -23,7 +23,7 @@
static td_err_e
iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
void *cbdata_p, td_thr_state_e state, int ti_pri,
- psaddr_t head, bool fake_empty, pid_t match_pid)
+ psaddr_t head, int *empty_count, pid_t match_pid)
{
td_err_e err;
psaddr_t next, ofs;
@@ -38,15 +38,11 @@ iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
if (err != TD_OK)
return err;
- if (next == 0 && fake_empty)
+ if (next == 0 || next == head)
{
- /* __pthread_initialize_minimal has not run. There is just the main
- thread to return. We cannot rely on its thread register. They
- sometimes contain garbage that would confuse us, left by the
- kernel at exec. So if it looks like initialization is incomplete,
- we only fake a special descriptor for the initial thread. */
- td_thrhandle_t th = { ta, 0 };
- return callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK;
+ /* The list is uninitialized or empty. */
+ (*empty_count)++;
+ return TD_OK;
}
/* Cache the offset from struct pthread to its list_t member. */
@@ -139,6 +135,7 @@ td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback,
td_thragent_t *const ta = (td_thragent_t *) ta_arg;
td_err_e err;
psaddr_t list = 0;
+ int empty_count = 0;
LOG ("td_ta_thr_iter");
@@ -157,14 +154,27 @@ td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback,
err = DB_GET_SYMBOL (list, ta, __stack_user);
if (err == TD_OK)
err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
- list, true, pid);
+ list, &empty_count, pid);
/* And the threads with stacks allocated by the implementation. */
if (err == TD_OK)
err = DB_GET_SYMBOL (list, ta, stack_used);
if (err == TD_OK)
err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
- list, false, pid);
+ list, &empty_count, pid);
+
+ if (err == TD_OK && empty_count == 2)
+ {
+ /* __pthread_initialize_minimal has not completed. We need to
+ call the callback for the main thread, but we cannot rely on
+ its thread register (they sometimes contain garbage that
+ would confuse us, left by the kernel at exec) so we fake a
+ special descriptor for the initial thread. */
+ td_thrhandle_t th = { ta, 0 };
+
+ if (callback (&th, cbdata_p) != 0)
+ err = TD_DBERR;
+ }
return err;
}