Re: [non-stop] 08/10 linux native support

Pedro Alves
2008-07-10T15:28:43Z

[-- Attachment #1: Type: text/plain, Size: 4664 bytes --]

On Monday 07 July 2008 19:20:09, Daniel Jacobowitz wrote:
> On Wed, Jul 02, 2008 at 04:34:50AM +0100, Pedro Alves wrote:

> > @@ -1720,20 +1811,54 @@ linux_handle_extended_wait (struct lwp_i
> > else
> > status = 0;
> >
> > +#if 0
> > + /* Make thread_db aware of this thread. We do this this
> > + early, so in non-stop mode, threads show up as they're
> > + created, instead of on next stop, and so that they have
> > + the correct running state. thread_db_find_new_threads
> > + needs a stopped inferior_ptid --- since we know LP is
> > + stopped, use it this time. */
> > + old_chain = save_inferior_ptid ();
> > + inferior_ptid = lp->ptid;
> > + lp->stopped = 1;
> > + target_find_new_threads ();
> > + do_cleanups (old_chain);
> > + if (!in_thread_list (new_lp->ptid))
> > +#else
> > + /* "Attach"ing to the parent forces the thread_db target to
> > + build its private data structures for the parent, which
> > + may have not had them setup yet. */
> > + thread_db_attach_lwp (lp->ptid);
> > + /* Do the same to the child, which, if thread_db is active,
> > + adds the child to GDB's thread list. */
> > + if (!thread_db_attach_lwp (new_lp->ptid))
> > +#endif
>
> This (the thread_db_attach_lwp version) looks reasonable to me. Ugly,
> but reasonable. Why do we need the parent's data?

Due to this:

(gdb) r&
Starting program: /home/pedro/gdb/tests/threads32
(gdb) [Thread debugging using libthread_db enabled]
[New Thread 0xf7df0b90 (LWP 24154)]
[New Thread 0xf75efb90 (LWP 24155)]
info threads
3 Thread 0xf75efb90 (LWP 24155) (running)
2 Thread 0xf7df0b90 (LWP 24154) (running)
* 1 LWP 24151 (running)
(gdb) interrupt
(gdb)
Program received signal SIGINT, Interrupt.
0xffffe410 in __kernel_vsyscall ()
info threads
During symbol reading, incomplete CFI data; unspecified registers (e.g., eax) at 0xffffe411.
3 Thread 0xf75efb90 (LWP 24155) (running)
2 Thread 0xf7df0b90 (LWP 24154) (running)
* 1 Thread 0xf7df16b0 (LWP 24151) 0xffffe410 in __kernel_vsyscall ()

This is where I had gotten myself stuck. The main thread id
isn't discovered until late when we stop. The thing is that the main
thread is already in GDB's thread list since very early, before
thread_db was detected. Since we can only query thread_db when we
have a stopped thread around, I couldn't find any other place to
learn about the main thread's thread_db id, until it has stopped.
Even doing it on PTRACE_EVENT_CLONE doesn't solve the
single-threaded + thread_db case.

Also, this happened:

(gdb) b 81
Breakpoint 1 at 0x80485fd: file threads.c, line 81.
(gdb) r
Starting program: /home/pedro/gdb/tests/threads32
[Thread debugging using libthread_db enabled]
[New Thread 0xf7dd8b90 (LWP 28225)]
[New Thread 0xf75d7b90 (LWP 28226)]

Breakpoint 1, thread_function1 (arg=0x1) at threads.c:81
81 usleep (1); /* Loop increment. */
(gdb) info threads
3 Thread 0xf75d7b90 (LWP 28226) thread_function1 (arg=0x1) at threads.c:81
2 Thread 0xf7dd8b90 (LWP 28225) (running)
* 1 LWP 28222 (running)

The issue here is that have_threads returns true here:

linux-thread-db.c:thread_db_wait
...
/* If we do not know about the main thread yet, this would be a good time to
find it. */
if (ourstatus->kind == TARGET_WAITKIND_STOPPED && !have_threads ())
thread_db_find_new_threads ();

... because there are already threads that thread_db learned about,
so we'd not look for info regarding the main thread.

The attached patch fixes these issues, by changing this bit above
to do:

if (ourstatus->kind == TARGET_WAITKIND_STOPPED)
/* If we do not know about the main thread yet, this would be a
good time to find it. */
iterate_over_threads (thread_db_claim_lwp_callback, &ptid);

... and adds the necessary glue for that.

>
> > + {
> > + /* We're not using thread_db. Attach and add it to
> > + GDB's list. */
> > + lin_lwp_attach_lwp (new_lp->ptid);
> > + target_post_attach (GET_LWP (new_lp->ptid));
> > + add_thread (new_lp->ptid);
> > + }
> > +
>
> Why do we need to call lin_lwp_attach_lwp? Won't that try to
> PTRACE_ATTACH? And we've already called add_lwp above.

It won't do PTRACE_ATTACH, exactly because we've already
called add_lwp above. Ah, I see. lin_lwp_attach_lwp will
only do lp->stopped = 1 in this case, the "attach to every
thread" thing is meant for the target_attach'ing case. I've
removed that call.

Apart from the what's mentioned above, nothing else changed.
Does the patch look closer to ok now?

I've regtested it on x86_64-unknown-linux-gnu.

--
Pedro Alves

[-- Attachment #2: 008-non_stop_linux.diff --]
[-- Type: text/x-diff, Size: 22222 bytes --]

2008-07-10 Pedro Alves <pedro@codesourcery.com>

Non-stop linux native.

* linux-nat.c (linux_test_for_tracefork): Block events while we're
here.
(find_lwp_pid): Rename to...
(linux_nat_find_lwp_pid): ... this. Make public. Update all
callers.
(get_pending_status): Implement non-stop mode.
(linux_nat_detach): Stop threads before detaching.
(linux_nat_resume): In non-stop mode, always resume only a single
PTID.
(linux_handle_extended_wait): In non-stop mode, on a clone event,
add new lwp to GDB's thread table, and mark as running, executing
and stopped appropriatelly.
(linux_nat_filter_event): Don't assume there are other running
threads when a thread exits.
(linux_nat_wait): Mark the main thread as running and executing.
In non-stop mode, don't stop all lwps.
(linux_nat_kill): Stop lwps before killing them.
(linux_nat_thread_alive): Use signal 0 to detect if a thread is
alive.
(send_sigint_callback): New.
(linux_nat_stop): New.
(linux_nat_add_target): Set to_stop to linux_nat_stop.

* linux-nat.h (thread_db_attach_lwp): Declare.
(linux_nat_find_lwp_pid): Declare.

* linux-thread-db.c (thread_from_lwp, enable_thread_event)
(check_event): Set proc_handle.pid to the stopped lwp.
(thread_db_attach_lwp, thread_db_attach_lwp_1): New.
(attach_thread): Don't set the private field if thread returns 0
as ti_tid.
(thread_db_claim_lwp_callback): New.
(thread_db_wait): Claim any thread that the thread_db target
didn't know about yet, but GDB's core did.
(thread_db_find_new_threads): If current lwp is executing, don't
try to read from it.

* linux-fork.c (linux_fork_killall): Use SIGKILL instead of
PTRACE_KILL.

---
gdb/linux-fork.c | 4
gdb/linux-nat.c | 250 ++++++++++++++++++++++++++++++++++++++++----------
gdb/linux-nat.h | 4
gdb/linux-thread-db.c | 95 +++++++++++++++++--
4 files changed, 295 insertions(+), 58 deletions(-)

Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c 2008-07-10 16:03:44.000000000 +0100
+++ src/gdb/linux-nat.c 2008-07-10 16:03:46.000000000 +0100
@@ -285,6 +285,9 @@ static void linux_nat_async (void (*call
static int linux_nat_async_mask (int mask);
static int kill_lwp (int lwpid, int signo);

+static int send_sigint_callback (struct lwp_info *lp, void *data);
+static int stop_callback (struct lwp_info *lp, void *data);
+
/* Captures the result of a successful waitpid call, along with the
options used in that call. */
struct waitpid_result
@@ -487,6 +490,9 @@ linux_test_for_tracefork (int original_p
{
int child_pid, ret, status;
long second_pid;
+ enum sigchld_state async_events_original_state;
+
+ async_events_original_state = linux_nat_async_events (sigchld_sync);

linux_supports_tracefork_flag = 0;
linux_supports_tracevforkdone_flag = 0;
@@ -517,6 +523,7 @@ linux_test_for_tracefork (int original_p
if (ret != 0)
{
warning (_("linux_test_for_tracefork: failed to kill child"));
+ linux_nat_async_events (async_events_original_state);
return;
}

@@ -527,6 +534,7 @@ linux_test_for_tracefork (int original_p
warning (_("linux_test_for_tracefork: unexpected wait status 0x%x from "
"killed child"), status);

+ linux_nat_async_events (async_events_original_state);
return;
}

@@ -566,6 +574,8 @@ linux_test_for_tracefork (int original_p
if (ret != 0)
warning (_("linux_test_for_tracefork: failed to kill child"));
my_waitpid (child_pid, &status, 0);
+
+ linux_nat_async_events (async_events_original_state);
}

/* Return non-zero iff we have tracefork functionality available.
@@ -985,8 +995,8 @@ delete_lwp (ptid_t ptid)
/* Return a pointer to the structure describing the LWP corresponding
to PID. If no corresponding LWP could be found, return NULL. */

-static struct lwp_info *
-find_lwp_pid (ptid_t ptid)
+struct lwp_info *
+linux_nat_find_lwp_pid (ptid_t ptid)
{
struct lwp_info *lp;
int lwp;
@@ -1207,7 +1217,7 @@ lin_lwp_attach_lwp (ptid_t ptid)

async_events_original_state = linux_nat_async_events (sigchld_sync);

- lp = find_lwp_pid (ptid);
+ lp = linux_nat_find_lwp_pid (ptid);

/* We assume that we're already attached to any LWP that has an id
equal to the overall process id, and to any LWP that is already
@@ -1376,16 +1386,80 @@ get_pending_status (struct lwp_info *lp,
events are always cached in waitpid_queue. */

*status = 0;
- if (GET_LWP (lp->ptid) == GET_LWP (last_ptid))
+
+ if (non_stop)
{
- if (stop_signal != TARGET_SIGNAL_0
- && signal_pass_state (stop_signal))
- *status = W_STOPCODE (target_signal_to_host (stop_signal));
+ enum target_signal signo = TARGET_SIGNAL_0;
+
+ if (is_executing (lp->ptid))
+ {
+ /* If the core thought this lwp was executing --- e.g., the
+ executing property hasn't been updated yet, but the
+ thread has been stopped with a stop_callback /
+ stop_wait_callback sequence (see linux_nat_detach for
+ example) --- we can only have pending events in the local
+ queue. */
+ if (queued_waitpid (GET_LWP (lp->ptid), status, __WALL) != -1)
+ {
+ if (WIFSTOPPED (status))
+ signo = target_signal_from_host (WSTOPSIG (status));
+
+ /* If not stopped, then the lwp is gone, no use in
+ resending a signal. */
+ }
+ }
+ else
+ {
+ /* If the core knows the thread is not executing, then we
+ have the last signal recorded in
+ thread_info->stop_signal, unless this is inferior_ptid,
+ in which case, it's in the global stop_signal, due to
+ context switching. */
+
+ if (ptid_equal (lp->ptid, inferior_ptid))
+ signo = stop_signal;
+ else
+ {
+ struct thread_info *tp = find_thread_pid (lp->ptid);
+ gdb_assert (tp);
+ signo = tp->stop_signal;
+ }
+ }
+
+ if (signo != TARGET_SIGNAL_0
+ && !signal_pass_state (signo))
+ {
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog, "\
+GPT: lwp %s had signal %s, but it is in no pass state\n",
+ target_pid_to_str (lp->ptid),
+ target_signal_to_string (signo));
+ }
+ else
+ {
+ if (signo != TARGET_SIGNAL_0)
+ *status = W_STOPCODE (target_signal_to_host (signo));
+
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "GPT: lwp %s as pending signal %s\n",
+ target_pid_to_str (lp->ptid),
+ target_signal_to_string (signo));
+ }
}
- else if (target_can_async_p ())
- queued_waitpid (GET_LWP (lp->ptid), status, __WALL);
else
- *status = lp->status;
+ {
+ if (GET_LWP (lp->ptid) == GET_LWP (last_ptid))
+ {
+ if (stop_signal != TARGET_SIGNAL_0
+ && signal_pass_state (stop_signal))
+ *status = W_STOPCODE (target_signal_to_host (stop_signal));
+ }
+ else if (target_can_async_p ())
+ queued_waitpid (GET_LWP (lp->ptid), status, __WALL);
+ else
+ *status = lp->status;
+ }

return 0;
}
@@ -1449,6 +1523,13 @@ linux_nat_detach (char *args, int from_t
if (target_can_async_p ())
linux_nat_async (NULL, 0);

+ /* Stop all threads before detaching. ptrace requires that the
+ thread is stopped to sucessfully detach. */
+ iterate_over_lwps (stop_callback, NULL);
+ /* ... and wait until all of them have reported back that
+ they're no longer running. */
+ iterate_over_lwps (stop_wait_callback, NULL);
+
iterate_over_lwps (detach_callback, NULL);

/* Only the initial process should be left right now. */
@@ -1538,19 +1619,27 @@ linux_nat_resume (ptid_t ptid, int step,
/* A specific PTID means `step only this process id'. */
resume_all = (PIDGET (ptid) == -1);

- if (resume_all)
- iterate_over_lwps (resume_set_callback, NULL);
- else
- iterate_over_lwps (resume_clear_callback, NULL);
+ if (non_stop && resume_all)
+ internal_error (__FILE__, __LINE__,
+ "can't resume all in non-stop mode");
+
+ if (!non_stop)
+ {
+ if (resume_all)
+ iterate_over_lwps (resume_set_callback, NULL);
+ else
+ iterate_over_lwps (resume_clear_callback, NULL);
+ }

/* If PID is -1, it's the current inferior that should be
handled specially. */
if (PIDGET (ptid) == -1)
ptid = inferior_ptid;

- lp = find_lwp_pid (ptid);
+ lp = linux_nat_find_lwp_pid (ptid);
gdb_assert (lp != NULL);

+ /* Convert to something the lower layer understands. */
ptid = pid_to_ptid (GET_LWP (lp->ptid));

/* Remember if we're stepping. */
@@ -1720,10 +1809,38 @@ linux_handle_extended_wait (struct lwp_i
else
status = 0;

+ if (non_stop)
+ {
+ /* Add the new thread to GDB's lists as soon as possible
+ so that:
+
+ 1) the frontend doesn't have to wait for a stop to
+ display them, and,
+
+ 2) we can tag it with the correct running state. */
+
+ /* If the thread_db layer is active, let it know about
+ this new thread. */
+ if (!thread_db_attach_lwp (new_lp->ptid))
+ {
+ /* We're not using thread_db. Add the thread to
+ GDB's list anyway. */
+ target_post_attach (GET_LWP (new_lp->ptid));
+ add_thread (new_lp->ptid);
+ }
+
+ if (!stopping)
+ {
+ set_executing (new_lp->ptid, 1);
+ set_running (new_lp->ptid, 1);
+ }
+ }
+
if (stopping)
new_lp->stopped = 1;
else
{
+ new_lp->stopped = 0;
new_lp->resumed = 1;
ptrace (PTRACE_CONT,
PIDGET (lp->waitstatus.value.related_pid), 0,
@@ -2368,7 +2485,7 @@ linux_nat_filter_event (int lwpid, int s
{
struct lwp_info *lp;

- lp = find_lwp_pid (pid_to_ptid (lwpid));
+ lp = linux_nat_find_lwp_pid (pid_to_ptid (lwpid));

/* Check for stop events reported by a process we didn't already
know about - anything not already in our LWP list.
@@ -2463,13 +2580,7 @@ linux_nat_filter_event (int lwpid, int s
not the end of the debugged application and should be
ignored. */
if (num_lwps > 0)
- {
- /* Make sure there is at least one thread running. */
- gdb_assert (iterate_over_lwps (running_callback, NULL));
-
- /* Discard the event. */
- return NULL;
- }
+ return NULL;
}

/* Check if the current LWP has previously exited. In the nptl
@@ -2599,6 +2710,8 @@ linux_nat_wait (ptid_t ptid, struct targ
lp->resumed = 1;
/* Add the main thread to GDB's thread list. */
add_thread_silent (lp->ptid);
+ set_running (lp->ptid, 1);
+ set_executing (lp->ptid, 1);
}

sigemptyset (&flush_mask);
@@ -2645,7 +2758,7 @@ retry:
target_pid_to_str (ptid));

/* We have a specific LWP to check. */
- lp = find_lwp_pid (ptid);
+ lp = linux_nat_find_lwp_pid (ptid);
gdb_assert (lp);
status = lp->status;
lp->status = 0;
@@ -2826,19 +2939,23 @@ retry:
fprintf_unfiltered (gdb_stdlog, "LLW: Candidate event %s in %s.\n",
status_to_str (status), target_pid_to_str (lp->ptid));

- /* Now stop all other LWP's ... */
- iterate_over_lwps (stop_callback, NULL);
+ if (!non_stop)
+ {
+ /* Now stop all other LWP's ... */
+ iterate_over_lwps (stop_callback, NULL);

- /* ... and wait until all of them have reported back that they're no
- longer running. */
- iterate_over_lwps (stop_wait_callback, &flush_mask);
- iterate_over_lwps (flush_callback, &flush_mask);
-
- /* If we're not waiting for a specific LWP, choose an event LWP from
- among those that have had events. Giving equal priority to all
- LWPs that have had events helps prevent starvation. */
- if (pid == -1)
- select_event_lwp (&lp, &status);
+ /* ... and wait until all of them have reported back that
+ they're no longer running. */
+ iterate_over_lwps (stop_wait_callback, &flush_mask);
+ iterate_over_lwps (flush_callback, &flush_mask);
+
+ /* If we're not waiting for a specific LWP, choose an event LWP
+ from among those that have had events. Giving equal priority
+ to all LWPs that have had events helps prevent
+ starvation. */
+ if (pid == -1)
+ select_event_lwp (&lp, &status);
+ }

/* Now that we've selected our final event LWP, cancel any
breakpoints in other LWPs that have hit a GDB breakpoint. See
@@ -2970,6 +3087,13 @@ linux_nat_kill (void)
}
else
{
+ /* Stop all threads before killing them, since ptrace requires
+ that the thread is stopped to sucessfully PTRACE_KILL. */
+ iterate_over_lwps (stop_callback, NULL);
+ /* ... and wait until all of them have reported back that
+ they're no longer running. */
+ iterate_over_lwps (stop_wait_callback, NULL);
+
/* Kill all LWP's ... */
iterate_over_lwps (kill_callback, NULL);

@@ -3022,22 +3146,22 @@ linux_nat_xfer_partial (struct target_op
static int
linux_nat_thread_alive (ptid_t ptid)
{
+ int err;
+
gdb_assert (is_lwp (ptid));

- errno = 0;
- ptrace (PTRACE_PEEKUSER, GET_LWP (ptid), 0, 0);
+ /* Send signal 0 instead of anything ptrace, because ptracing a
+ running thread errors out claiming that the thread doesn't
+ exist. */
+ err = kill_lwp (GET_LWP (ptid), 0);
+
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
- "LLTA: PTRACE_PEEKUSER %s, 0, 0 (%s)\n",
+ "LLTA: KILL(SIG0) %s (%s)\n",
target_pid_to_str (ptid),
- errno ? safe_strerror (errno) : "OK");
+ err ? safe_strerror (err) : "OK");

- /* Not every Linux kernel implements PTRACE_PEEKUSER. But we can
- handle that case gracefully since ptrace will first do a lookup
- for the process based upon the passed-in pid. If that fails we
- will get either -ESRCH or -EPERM, otherwise the child exists and
- is alive. */
- if (errno == ESRCH || errno == EPERM)
+ if (err != 0)
return 0;

return 1;
@@ -4239,6 +4363,35 @@ linux_nat_set_async_mode (int on)
linux_nat_async_enabled = on;
}

+static int
+send_sigint_callback (struct lwp_info *lp, void *data)
+{
+ /* Use is_running instead of !lp->stopped, because the lwp may be
+ stopped due to an internal event, and we want to interrupt it in
+ that case too. What we want is to check if the thread is stopped
+ from the point of view of the user. */
+ if (is_running (lp->ptid))
+ kill_lwp (GET_LWP (lp->ptid), SIGINT);
+ return 0;
+}
+
+static void
+linux_nat_stop (ptid_t ptid)
+{
+ if (non_stop)
+ {
+ if (ptid_equal (ptid, minus_one_ptid))
+ iterate_over_lwps (send_sigint_callback, &ptid);
+ else
+ {
+ struct lwp_info *lp = linux_nat_find_lwp_pid (ptid);
+ send_sigint_callback (lp, NULL);
+ }
+ }
+ else
+ linux_ops->to_stop (ptid);
+}
+
void
linux_nat_add_target (struct target_ops *t)
{
@@ -4269,6 +4422,9 @@ linux_nat_add_target (struct target_ops
t->to_terminal_inferior = linux_nat_terminal_inferior;
t->to_terminal_ours = linux_nat_terminal_ours;

+ /* Methods for non-stop support. */
+ t->to_stop = linux_nat_stop;
+
/* We don't change the stratum; this target will sit at
process_stratum and thread_db will set at thread_stratum. This
is a little strange, since this is a multi-threaded-capable
@@ -4296,7 +4452,7 @@ linux_nat_set_new_thread (struct target_
struct siginfo *
linux_nat_get_siginfo (ptid_t ptid)
{
- struct lwp_info *lp = find_lwp_pid (ptid);
+ struct lwp_info *lp = linux_nat_find_lwp_pid (ptid);

gdb_assert (lp != NULL);

Index: src/gdb/linux-nat.h
===================================================================
--- src.orig/gdb/linux-nat.h 2008-07-10 16:03:44.000000000 +0100
+++ src/gdb/linux-nat.h 2008-07-10 16:03:46.000000000 +0100
@@ -94,6 +94,8 @@ void check_for_thread_db (void);
/* Tell the thread_db layer what native target operations to use. */
void thread_db_init (struct target_ops *);

+int thread_db_attach_lwp (ptid_t ptid);
+
/* Find process PID's pending signal set from /proc/pid/status. */
void linux_proc_pending_signals (int pid, sigset_t *pending, sigset_t *blocked, sigset_t *ignored);

@@ -107,6 +109,8 @@ struct lwp_info *iterate_over_lwps (int
void *),
void *data);

+struct lwp_info *linux_nat_find_lwp_pid (ptid_t ptid);
+
/* Create a prototype generic GNU/Linux target. The client can
override it with local methods. */
struct target_ops * linux_target (void);
Index: src/gdb/linux-thread-db.c
===================================================================
--- src.orig/gdb/linux-thread-db.c 2008-07-10 16:03:44.000000000 +0100
+++ src/gdb/linux-thread-db.c 2008-07-10 16:14:30.000000000 +0100
@@ -308,6 +308,8 @@ thread_from_lwp (ptid_t ptid)
LWP. */
gdb_assert (GET_LWP (ptid) != 0);

+ /* Access an lwp we know is stopped. */
+ proc_handle.pid = GET_LWP (ptid);
err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
if (err != TD_OK)
error (_("Cannot find user-level thread for LWP %ld: %s"),
@@ -332,6 +334,49 @@ thread_from_lwp (ptid_t ptid)
}
\f

+/* Attach to lwp PTID, doing whatever else is required to have this
+ LWP under the debugger's control --- e.g., enabling event
+ reporting. Access thread_db through STOPPED_PTID. Returns true on
+ success. */
+static int
+thread_db_attach_lwp_1 (ptid_t stopped_ptid, ptid_t ptid)
+{
+ td_thrhandle_t th;
+ td_thrinfo_t ti;
+ td_err_e err;
+
+ if (!using_thread_db)
+ return 0;
+
+ /* This ptid comes from linux-nat.c, which should always fill in the
+ LWP. */
+ gdb_assert (GET_LWP (ptid) != 0);
+
+ /* Access an lwp we know is stopped. */
+ proc_handle.pid = GET_LWP (stopped_ptid);
+ err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+ if (err != TD_OK)
+ /* Cannot find user-level thread. */
+ return 0;
+
+ err = td_thr_get_info_p (&th, &ti);
+ if (err != TD_OK)
+ {
+ warning (_("Cannot get thread info: %s"), thread_db_err_str (err));
+ return 0;
+ }
+
+ attach_thread (ptid, &th, &ti);
+ return 1;
+}
+
+/* Same as thread_db_attach_lwp_1, but assume PTID is stopped. */
+int
+thread_db_attach_lwp (ptid_t ptid)
+{
+ return thread_db_attach_lwp_1 (ptid, ptid);
+}
+
void
thread_db_init (struct target_ops *target)
{
@@ -418,6 +463,9 @@ enable_thread_event (td_thragent_t *thre
td_notify_t notify;
td_err_e err;

+ /* Access an lwp we know is stopped. */
+ proc_handle.pid = GET_LWP (inferior_ptid);
+
/* Get the breakpoint address for thread EVENT. */
err = td_ta_event_addr_p (thread_agent, event, &notify);
if (err != TD_OK)
@@ -685,16 +733,22 @@ attach_thread (ptid_t ptid, const td_thr
&& lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))) < 0)
return;

+ if (ti_p->ti_tid == 0)
+ {
+ /* A thread ID of zero may mean the thread library has not
+ initialized yet. Leave it with private == NULL until the
+ thread_db target claims it. */
+
+ /* We should only get here if GDB already knew about this
+ thread. */
+ gdb_assert (tp != NULL);
+ return;
+ }
+
/* Construct the thread's private data. */
private = xmalloc (sizeof (struct private_thread_info));
memset (private, 0, sizeof (struct private_thread_info));

- /* A thread ID of zero may mean the thread library has not initialized
- yet. But we shouldn't even get here if that's the case. FIXME:
- if we change GDB to always have at least one thread in the thread
- list this will have to go somewhere else; maybe private == NULL
- until the thread_db target claims it. */
- gdb_assert (ti_p->ti_tid != 0);
private->th = *th_p;
private->tid = ti_p->ti_tid;

@@ -761,6 +815,9 @@ check_event (ptid_t ptid)
if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr)
return;

+ /* Access an lwp we know is stopped. */
+ proc_handle.pid = GET_LWP (ptid);
+
/* If we are at a create breakpoint, we do not know what new lwp
was created and cannot specifically locate the event message for it.
We have to call td_ta_event_getmsg() to get
@@ -820,6 +877,17 @@ check_event (ptid_t ptid)
while (loop);
}

+/* Claim threads the lower layer added, but that we didn't know about
+ yet. */
+static int
+thread_db_claim_lwp_callback (struct thread_info *tp, void *arg)
+{
+ ptid_t *stopped_ptid = arg;
+ if (tp && tp->private == NULL)
+ thread_db_attach_lwp_1 (*stopped_ptid, tp->ptid);
+ return 0;
+}
+
static ptid_t
thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
@@ -841,10 +909,10 @@ thread_db_wait (ptid_t ptid, struct targ
return ptid;
}

- /* If we do not know about the main thread yet, this would be a good time to
- find it. */
- if (ourstatus->kind == TARGET_WAITKIND_STOPPED && !have_threads ())
- thread_db_find_new_threads ();
+ if (ourstatus->kind == TARGET_WAITKIND_STOPPED)
+ /* If we do not know about the main thread yet, this would be a
+ good time to find it. */
+ iterate_over_threads (thread_db_claim_lwp_callback, &ptid);

if (ourstatus->kind == TARGET_WAITKIND_STOPPED
&& ourstatus->value.sig == TARGET_SIGNAL_TRAP)
@@ -955,7 +1023,14 @@ static void
thread_db_find_new_threads (void)
{
td_err_e err;
+ struct lwp_info *lp = linux_nat_find_lwp_pid (inferior_ptid);
+
+ if (!lp || !lp->stopped)
+ /* In linux, we can only read memory through a stopped lwp. */
+ return;

+ /* Access an lwp we know is stopped. */
+ proc_handle.pid = GET_LWP (inferior_ptid);
/* Iterate over all user-space threads to discover new threads. */
err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
Index: src/gdb/linux-fork.c
===================================================================
--- src.orig/gdb/linux-fork.c 2008-07-10 16:03:44.000000000 +0100
+++ src/gdb/linux-fork.c 2008-07-10 16:03:46.000000000 +0100
@@ -337,7 +337,9 @@ linux_fork_killall (void)
{
pid = PIDGET (fp->ptid);
do {
- ptrace (PT_KILL, pid, 0, 0);
+ /* Use SIGKILL instead of PTRACE_KILL because the former works even
+ if the thread is running, while the later doesn't. */
+ kill (pid, SIGKILL);
ret = waitpid (pid, &status, 0);
/* We might get a SIGCHLD instead of an exit status. This is
aggravated by the first kill above - a child has just