From ca1bbff0ee443807a36d8c7bf798672589ac37f6 Mon Sep 17 00:00:00 2001 From: joseph Date: Thu, 27 Mar 2008 13:22:15 +0000 Subject: Merge changes between r5247 and r5678 from /fsf/trunk. git-svn-id: svn://svn.eglibc.org/trunk@5679 7b3dc134-2b1b-0410-93df-9e9f96275f8d --- libc/nptl_db/ChangeLog | 9 ++++++ libc/nptl_db/structs.def | 3 +- libc/nptl_db/td_ta_thr_iter.c | 65 ++++++++++++++++++++++++++++-------------- libc/nptl_db/td_thr_validate.c | 26 ++++++++++++++++- 4 files changed, 79 insertions(+), 24 deletions(-) (limited to 'libc/nptl_db') diff --git a/libc/nptl_db/ChangeLog b/libc/nptl_db/ChangeLog index b4e311029..af819c301 100644 --- a/libc/nptl_db/ChangeLog +++ b/libc/nptl_db/ChangeLog @@ -1,3 +1,12 @@ +2008-03-25 Roland McGrath + + [BZ #5983] + * structs.def: Add pid field of struct pthread. + * td_ta_thr_iter.c (iterate_thread_list): Take new arg MATCH_PID. + If a thread's pid does not match nor is < 0 while its tid matches + nor is < 0 and equal to -MATCH_PID, ignore it. + * td_thr_validate.c (td_thr_validate): Validate thread's pid/tid. + 2007-05-16 Roland McGrath * td_thr_get_info.c: Fake the results for TH->th_unique == 0. diff --git a/libc/nptl_db/structs.def b/libc/nptl_db/structs.def index f5559ccb0..75da95a36 100644 --- a/libc/nptl_db/structs.def +++ b/libc/nptl_db/structs.def @@ -1,5 +1,5 @@ /* List of types and symbols in libpthread examined by libthread_db. - Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2003, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -27,6 +27,7 @@ DB_STRUCT (pthread) DB_STRUCT_FIELD (pthread, list) DB_STRUCT_FIELD (pthread, report_events) DB_STRUCT_FIELD (pthread, tid) +DB_STRUCT_FIELD (pthread, pid) DB_STRUCT_FIELD (pthread, start_routine) DB_STRUCT_FIELD (pthread, cancelhandling) DB_STRUCT_FIELD (pthread, schedpolicy) diff --git a/libc/nptl_db/td_ta_thr_iter.c b/libc/nptl_db/td_ta_thr_iter.c index c82f39cb7..9a594ed1d 100644 --- a/libc/nptl_db/td_ta_thr_iter.c +++ b/libc/nptl_db/td_ta_thr_iter.c @@ -1,5 +1,5 @@ /* Iterate over a process's threads. - Copyright (C) 1999,2000,2001,2002,2003,2004,2007 + Copyright (C) 1999,2000,2001,2002,2003,2004,2007,2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1999. @@ -25,7 +25,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) + psaddr_t head, bool fake_empty, pid_t match_pid) { td_err_e err; psaddr_t next, ofs; @@ -78,28 +78,48 @@ iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback, if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK) return TD_ERR; - err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread, - schedpolicy, 0); - if (err != TD_OK) - break; - err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread, - schedparam_sched_priority, 0); + /* Verify that this thread's pid field matches the child PID. + If its pid field is negative, it's about to do a fork or it + is the sole thread in a fork child. */ + psaddr_t pid; + err = DB_GET_FIELD_LOCAL (pid, ta, copy, pthread, pid, 0); + if (err == TD_OK && (pid_t) (uintptr_t) pid < 0) + { + if (-(pid_t) (uintptr_t) pid == match_pid) + /* It is about to do a fork, but is really still the parent PID. */ + pid = (psaddr_t) (uintptr_t) match_pid; + else + /* It must be a fork child, whose new PID is in the tid field. */ + err = DB_GET_FIELD_LOCAL (pid, ta, copy, pthread, tid, 0); + } if (err != TD_OK) break; - /* Now test whether this thread matches the specified conditions. */ - - /* Only if the priority level is as high or higher. */ - int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER - ? 0 : (uintptr_t) schedprio); - if (descr_pri >= ti_pri) + if ((pid_t) (uintptr_t) pid == match_pid) { - /* Yep, it matches. Call the callback function. */ - td_thrhandle_t th; - th.th_ta_p = (td_thragent_t *) ta; - th.th_unique = addr; - if (callback (&th, cbdata_p) != 0) - return TD_DBERR; + err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread, + schedpolicy, 0); + if (err != TD_OK) + break; + err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread, + schedparam_sched_priority, 0); + if (err != TD_OK) + break; + + /* Now test whether this thread matches the specified conditions. */ + + /* Only if the priority level is as high or higher. */ + int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER + ? 0 : (uintptr_t) schedprio); + if (descr_pri >= ti_pri) + { + /* Yep, it matches. Call the callback function. */ + td_thrhandle_t th; + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = addr; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + } } /* Get the pointer to the next element. */ @@ -135,17 +155,18 @@ td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback, have to iterate over both lists separately. We start with the list of threads with user-defined stacks. */ + pid_t pid = ps_getpid (ta->ph); 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); + list, true, 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); + list, false, pid); return err; } diff --git a/libc/nptl_db/td_thr_validate.c b/libc/nptl_db/td_thr_validate.c index 9a77250d4..adcde3c87 100644 --- a/libc/nptl_db/td_thr_validate.c +++ b/libc/nptl_db/td_thr_validate.c @@ -1,5 +1,6 @@ /* Validate a thread handle. - Copyright (C) 1999,2001,2002,2003,2004,2007 Free Software Foundation, Inc. + Copyright (C) 1999,2001,2002,2003,2004,2007,2008 + Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1999. @@ -81,5 +82,28 @@ td_thr_validate (const td_thrhandle_t *th) err = TD_OK; } + if (err == TD_OK) + { + /* Verify that this is not a stale element in a fork child. */ + pid_t match_pid = ps_getpid (th->th_ta_p->ph); + psaddr_t pid; + err = DB_GET_FIELD (pid, th->th_ta_p, th->th_unique, pthread, pid, 0); + if (err == TD_OK && (pid_t) (uintptr_t) pid < 0) + { + /* This was a thread that was about to fork, or it is the new sole + thread in a fork child. In the latter case, its tid was stored + via CLONE_CHILD_SETTID and so is already the proper child PID. */ + if (-(pid_t) (uintptr_t) pid == match_pid) + /* It is about to do a fork, but is really still the parent PID. */ + pid = (psaddr_t) (uintptr_t) match_pid; + else + /* It must be a fork child, whose new PID is in the tid field. */ + err = DB_GET_FIELD (pid, th->th_ta_p, th->th_unique, + pthread, tid, 0); + } + if (err == TD_OK && (pid_t) (uintptr_t) pid != match_pid) + err = TD_NOTHR; + } + return err; } -- cgit v1.2.3