Draft patch (for GDB-CVS) proposal for handling+tracing behing pthread_exit(3) Patch disables handling of the TD_DEATH notification from __nptl_death_event() and tries to keep the thread in TD_THR_ZOMBIE state as long as possible before its LWP ceases to be. While expecting regressions so far no such was found, statistically it improves some testcases (+24 passes,-14 fails), no negatives. ('longjmp' part not resolved; not reproducible for GDB-CVS) Index: linux-thread-db.c =================================================================== RCS file: /cvs/src/src/gdb/linux-thread-db.c,v retrieving revision 1.16 diff -u -p -r1.16 linux-thread-db.c --- linux-thread-db.c 5 May 2006 22:42:43 -0000 1.16 +++ linux-thread-db.c 19 Jun 2006 16:27:16 -0000 @@ -541,6 +541,7 @@ enable_thread_event_reporting (void) td_event_emptyset (&events); td_event_addset (&events, TD_CREATE); +#if 0 /* Do not track TD_DEATH to be able to trace pthread_exit(3). */ #ifdef HAVE_GNU_LIBC_VERSION_H /* FIXME: kettenis/2000-04-23: The event reporting facility is broken for TD_DEATH events in glibc 2.1.3, so don't enable it for @@ -550,6 +551,7 @@ enable_thread_event_reporting (void) && (libc_major > 2 || (libc_major == 2 && libc_minor > 1))) #endif td_event_addset (&events, TD_DEATH); +#endif err = td_ta_set_event_p (thread_agent, &events); if (err != TD_OK) @@ -573,6 +575,7 @@ enable_thread_event_reporting (void) return; } +#if 0 /* Do not track TD_DEATH to be able to trace pthread_exit(3). */ /* Set up the thread death event. */ err = enable_thread_event (thread_agent, TD_DEATH, &td_death_bp_addr); if (err != TD_OK) @@ -581,6 +584,7 @@ enable_thread_event_reporting (void) thread_db_err_str (err)); return; } +#endif } static void @@ -1006,6 +1010,9 @@ thread_db_fetch_registers (int regno) } thread_info = find_thread_pid (inferior_ptid); + if (!thread_info) + error (_("Stopped at dead thread %ld; should not happen."), + (long) GET_THREAD (inferior_ptid)); thread_db_map_id2thr (thread_info, 1); err = td_thr_getgregs_p (&thread_info->private->th, gregset); @@ -1127,6 +1134,8 @@ thread_db_thread_alive (ptid_t ptid) struct thread_info *thread_info; thread_info = find_thread_pid (ptid); + if (!thread_info) + return 0; thread_db_map_id2thr (thread_info, 0); if (!thread_info->private->th_valid) return 0; @@ -1145,9 +1154,9 @@ thread_db_thread_alive (ptid_t ptid) thread_info->private->ti_valid = 1; } - if (thread_info->private->ti.ti_state == TD_THR_UNKNOWN - || thread_info->private->ti.ti_state == TD_THR_ZOMBIE) - return 0; /* A zombie thread. */ + /* Never 0 on TD_THR_ZOMBIE to be able to trace pthread_exit(3). */ + if (thread_info->private->ti.ti_state == TD_THR_UNKNOWN) + return 0; /* A disappeared thread. */ return 1; }