diff options
-rw-r--r-- | nptl_db/td_thr_event_getmsg.c | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/nptl_db/td_thr_event_getmsg.c b/nptl_db/td_thr_event_getmsg.c index ffd0baadc5..9008633289 100644 --- a/nptl_db/td_thr_event_getmsg.c +++ b/nptl_db/td_thr_event_getmsg.c @@ -1,5 +1,5 @@ /* Retrieve event. - Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. @@ -31,7 +31,7 @@ td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg) LOG ("td_thr_event_getmsg"); - /* Read the even structure from the target. */ + /* Read the event structure from the target. */ if (ps_pdread (th->th_ta_p->ph, ((char *) th->th_unique + offsetof (struct pthread, eventbuf)), @@ -56,5 +56,50 @@ td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg) &event, sizeof (td_eventbuf_t)) != PS_OK) return TD_ERR; /* XXX Other error value? */ - return TD_OK; + /* Get the pointer to the thread descriptor with the last event. + If it doesn't match TH, then walk down the list until we find it. + We must splice it out of the list so that there is no dangling + pointer to it later when it dies. */ + psaddr_t thp, prevp = th->th_ta_p->pthread_last_event; + if (ps_pdread (th->th_ta_p->ph, + prevp, &thp, sizeof (struct pthread *)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + psaddr_t next; + while (thp != 0) + { + if (ps_pdread (th->th_ta_p->ph, + (char *) thp + offsetof (struct pthread, nextevent), + &next, sizeof (struct pthread *)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (next == thp) + return TD_DBERR; + + if (thp == th->th_unique) + { + /* PREVP points at this thread, splice it out. */ + if (prevp == (char *) next + offsetof (struct pthread, nextevent)) + return TD_DBERR; + + if (ps_pdwrite (th->th_ta_p->ph, prevp, &next, sizeof next) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now clear this thread's own next pointer so it's not dangling + when the thread resumes and then chains on for its next event. */ + next = NULL; + if (ps_pdwrite (th->th_ta_p->ph, + (char *) thp + offsetof (struct pthread, nextevent), + &next, sizeof next) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; + } + + prevp = (char *) thp + offsetof (struct pthread, nextevent); + thp = next; + } + + /* Ack! This should not happen. */ + return TD_DBERR; } |