diff options
author | Pedro Alves <palves@redhat.com> | 2009-05-18 14:07:18 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2009-05-18 14:07:18 +0000 |
commit | d90e17a74d28db7b3632eced357327ce2fb14f01 (patch) | |
tree | 1706c006f2d1becd31b2f5a07c310ce2e9f4d193 /gdb/linux-nat.c | |
parent | dddfab26ac67f22f609b7cd61318a2fca0b319e8 (diff) | |
download | gdb-d90e17a74d28db7b3632eced357327ce2fb14f01.zip gdb-d90e17a74d28db7b3632eced357327ce2fb14f01.tar.gz gdb-d90e17a74d28db7b3632eced357327ce2fb14f01.tar.bz2 |
* fork-child.c (fork_inferior): Only reset the thread list if this
is the first inferior.
(startup_inferior): If the target support multi-process, tell it
to resume only the new process.
* linux-nat.c (num_lwps): Delete global.
(purge_lwp_list): New function.
(num_lwps): New function.
(add_lwp, delete_lwp): Adjust.
(ptid_match): New.
(iterate_over_lwps): Add filter argument. Handle it.
(linux_nat_attach): Remove FIXME note.
(linux_nat_detach): Adjust to iterate over threads of the inferior
we're detaching from. Adjust to num_lwps being a function. Don't
assume the head of the lwp list is the main thread of the process
we're detaching from. Don't destroy the LWP list.
(resume_callback): Add debug output.
(linux_nat_resume): Handle resuming a single inferior. Allow a
wildcard resume in non-stop mode.
(linux_handle_extended_wait): Don't assume inferior_ptid is the
correct inferior of the parent LWP.
(status_callback): Also check lp->waitstatus.
(select_event_lwp): Add new filter parameter. Handle it.
(linux_nat_filter_event): Adjust to num_lwps being a function.
(linux_nat_wait_1): When adding the first lwp of the inferior, use
an is_lwp check instead of checking for the number of lwps.
(linux_nat_wait_1): Handle waiting for a specific tgid. Handle
pending process exit statuses.
(linux_nat_mourn_inferior): Don't destroy all the LWP info.
Instead delete LWPs of the inferior that we're mourning. Don't
unregister from the event loop here.
(linux_nat_pid_to_str): Use `num_lwps'.
(linux_nat_make_corefile_notes): Adjust to walk over lwps of a
single inferior.
(linux_nat_is_async_p): Check if async was masked out.
(linux_multi_process): New global.
(linux_nat_supports_multi_process): New.
(linux_nat_stop_lwp): Remove LWP filtering. It is done by the
caller.
(linux_nat_stop): Adjust to make iterate_over_lwps itself do the
LWP filtering.
(linux_nat_close): New.
(linux_nat_add_target): Register linux_nat_close and
linux_nat_supports_multi_process.
* linux-nat.h (iterate_over_lwps): Add filter argument.
* linux-thread-db.c (thread_db_handle): Delete.
(proc_handle, thread_agent, td_init_p, td_ta_new_p)
(td_ta_map_id2thr_p, td_ta_map_lwp2thr_p, td_ta_thr_iter_p)
(td_ta_event_addr_p, td_ta_set_event_p, td_ta_event_getmsg_p)
(td_thr_validate_p, td_thr_get_info_p, td_thr_event_enable_p)
(td_thr_tls_get_addr_p, td_create_bp_addr, td_death_bp_addr): No
longer globals, moved to...
(struct thread_db_info): ... this new structure.
(thread_db_list): New.
(add_thread_db_info, get_thread_db_info, delete_thread_db_info):
New.
(have_threads_callback): Filter out threads of all inferiors but
the one specified by the ARGS argument.
(have_threads): Add ptid argument specifying the inferior we're
interested in. Handle it.
(struct thread_get_info_inout): New.
(thread_get_info_callback, thread_from_lwp): Adjust to use it.
(thread_db_attach_lwp): Check that inferior of the passed in
thread is using thread-db. Adjust.
(enable_thread_event): Remove thread_agent parameter. Instead,
get it from the per-inferior thread-db info.
(dladdr_to_soname): Move higher up.
(enable_thread_event_reporting): Adjust to use per-inferior
thread-db info.
(try_thread_db_load_1): Replace `handle' parameter by a
thread_db_info parameter. Adjust to use per-inferior thread-db
info.
(try_thread_db_load): Adjust to use per-inferior thread-db info.
(thread_db_load, disable_thread_event_reporting): Ditto.
(check_for_thread_db): Remove conditional reporting of which
libthread_db is in use.
(thread_db_new_objfile): Add comment about inferior_ptid.
(attach_thread): Adjust to use per-inferior thread-db info.
(thread_db_detach): Adjust to use per-inferior thread-db info.
Remove thread event breakpoints of the current inferior. Only
unpush the thread-db target if there are no more processes using
it.
(check_event): Adjust to use per-inferior thread-db info.
(thread_db_wait): Adjust to use per-inferior thread-db info. Only
unpush the thread-db target if there are no more processes using
it.
(thread_db_mourn_inferior): Adjust to use per-inferior thread-db
info. Mark breakpoints of the current inferior out before
deleting them. Only unpush the thread-db target if there are no
more processes using it.
(find_new_threads_callback): Adjust to use per-inferior thread_db
info.
(thread_db_find_new_threads_1): Add new ptid argument. Adjust to
use per-inferior thread-db info.
(thread_db_find_new_threads): Adjust to use per-inferior thread-db
info.
(thread_db_get_thread_local_address): Adjust.
(thread_db_get_ada_task_ptid): Adjust.
* inf-ptrace.c (inf_ptrace_mourn_inferior): Only unpush the target
if there no more processes left to debug.
* thread.c (set_running, set_executing): Handle resuming all
threads of a single inferior.
* mi/mi-interp.c (mi_output_running_pid): New.
(mi_inferior_count): New.
(mi_on_resume): For backwards compatibility, if resuming all
threads of an inferior, and there is only one inferior, output
"all".
Diffstat (limited to 'gdb/linux-nat.c')
-rw-r--r-- | gdb/linux-nat.c | 453 |
1 files changed, 316 insertions, 137 deletions
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index beff012..553d676 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -841,9 +841,6 @@ linux_child_insert_exec_catchpoint (int pid) /* List of known LWPs. */ struct lwp_info *lwp_list; - -/* Number of LWPs in the list. */ -static int num_lwps; /* Original signal mask. */ @@ -926,7 +923,48 @@ init_lwp_list (void) } lwp_list = NULL; - num_lwps = 0; +} + +/* Remove all LWPs belong to PID from the lwp list. */ + +static void +purge_lwp_list (int pid) +{ + struct lwp_info *lp, *lpprev, *lpnext; + + lpprev = NULL; + + for (lp = lwp_list; lp; lp = lpnext) + { + lpnext = lp->next; + + if (ptid_get_pid (lp->ptid) == pid) + { + if (lp == lwp_list) + lwp_list = lp->next; + else + lpprev->next = lp->next; + + xfree (lp); + } + else + lpprev = lp; + } +} + +/* Return the number of known LWPs in the tgid given by PID. */ + +static int +num_lwps (int pid) +{ + int count = 0; + struct lwp_info *lp; + + for (lp = lwp_list; lp; lp = lp->next) + if (ptid_get_pid (lp->ptid) == pid) + count++; + + return count; } /* Add the LWP specified by PID to the list. Return a pointer to the @@ -950,9 +988,8 @@ add_lwp (ptid_t ptid) lp->next = lwp_list; lwp_list = lp; - ++num_lwps; - if (num_lwps > 1 && linux_nat_new_thread != NULL) + if (num_lwps (GET_PID (ptid)) > 1 && linux_nat_new_thread != NULL) linux_nat_new_thread (ptid); return lp; @@ -974,8 +1011,6 @@ delete_lwp (ptid_t ptid) if (!lp) return; - num_lwps--; - if (lpprev) lpprev->next = lp->next; else @@ -1005,21 +1040,54 @@ find_lwp_pid (ptid_t ptid) return NULL; } +/* Returns true if PTID matches filter FILTER. FILTER can be the wild + card MINUS_ONE_PTID (all ptid match it); can be a ptid representing + a process (ptid_is_pid returns true), in which case, all lwps of + that give process match, lwps of other process do not; or, it can + represent a specific thread, in which case, only that thread will + match true. PTID must represent an LWP, it can never be a wild + card. */ + +static int +ptid_match (ptid_t ptid, ptid_t filter) +{ + /* Since both parameters have the same type, prevent easy mistakes + from happening. */ + gdb_assert (!ptid_equal (ptid, minus_one_ptid) + && !ptid_equal (ptid, null_ptid)); + + if (ptid_equal (filter, minus_one_ptid)) + return 1; + if (ptid_is_pid (filter) + && ptid_get_pid (ptid) == ptid_get_pid (filter)) + return 1; + else if (ptid_equal (ptid, filter)) + return 1; + + return 0; +} + /* Call CALLBACK with its second argument set to DATA for every LWP in the list. If CALLBACK returns 1 for a particular LWP, return a pointer to the structure describing that LWP immediately. Otherwise return NULL. */ struct lwp_info * -iterate_over_lwps (int (*callback) (struct lwp_info *, void *), void *data) +iterate_over_lwps (ptid_t filter, + int (*callback) (struct lwp_info *, void *), + void *data) { struct lwp_info *lp, *lpnext; for (lp = lwp_list; lp; lp = lpnext) { lpnext = lp->next; - if ((*callback) (lp, data)) - return lp; + + if (ptid_match (lp->ptid, filter)) + { + if ((*callback) (lp, data)) + return lp; + } } return NULL; @@ -1296,8 +1364,6 @@ linux_nat_attach (struct target_ops *ops, char *args, int from_tty) int status; ptid_t ptid; - /* FIXME: We should probably accept a list of process id's, and - attach all of them. */ linux_ops->to_attach (ops, args, from_tty); /* The ptrace base target adds the main thread with (pid,0,0) @@ -1457,25 +1523,30 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty) int pid; int status; enum target_signal sig; + struct lwp_info *main_lwp; + + pid = GET_PID (inferior_ptid); 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); + iterate_over_lwps (pid_to_ptid (pid), 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 (pid_to_ptid (pid), stop_wait_callback, NULL); - iterate_over_lwps (detach_callback, NULL); + iterate_over_lwps (pid_to_ptid (pid), detach_callback, NULL); /* Only the initial process should be left right now. */ - gdb_assert (num_lwps == 1); + gdb_assert (num_lwps (GET_PID (inferior_ptid)) == 1); + + main_lwp = find_lwp_pid (pid_to_ptid (pid)); /* Pass on any pending signal for the last LWP. */ if ((args == NULL || *args == '\0') - && get_pending_status (lwp_list, &status) != -1 + && get_pending_status (main_lwp, &status) != -1 && WIFSTOPPED (status)) { /* Put the signal number in ARGS so that inf_ptrace_detach will @@ -1485,13 +1556,10 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty) fprintf_unfiltered (gdb_stdlog, "LND: Sending signal %s to %s\n", args, - target_pid_to_str (lwp_list->ptid)); + target_pid_to_str (main_lwp->ptid)); } - /* Destroy LWP info; it's no longer valid. */ - init_lwp_list (); - - pid = ptid_get_pid (inferior_ptid); + delete_lwp (main_lwp->ptid); if (forks_exist_p ()) { @@ -1515,6 +1583,11 @@ resume_callback (struct lwp_info *lp, void *data) { if (lp->stopped && lp->status == 0) { + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "RC: PTRACE_CONT %s, 0, 0 (resuming sibling)\n", + target_pid_to_str (lp->ptid)); + linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)), 0, TARGET_SIGNAL_0); @@ -1556,7 +1629,7 @@ linux_nat_resume (struct target_ops *ops, { sigset_t prev_mask; struct lwp_info *lp; - int resume_all; + int resume_many; if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, @@ -1569,37 +1642,29 @@ linux_nat_resume (struct target_ops *ops, block_child_signals (&prev_mask); /* A specific PTID means `step only this process id'. */ - resume_all = (PIDGET (ptid) == -1); - - if (non_stop && resume_all) - internal_error (__FILE__, __LINE__, - "can't resume all in non-stop mode"); + resume_many = (ptid_equal (minus_one_ptid, ptid) + || ptid_is_pid (ptid)); if (!non_stop) { - if (resume_all) - iterate_over_lwps (resume_set_callback, NULL); - else - iterate_over_lwps (resume_clear_callback, NULL); + /* Mark the lwps we're resuming as resumed. */ + iterate_over_lwps (minus_one_ptid, resume_clear_callback, NULL); + iterate_over_lwps (ptid, resume_set_callback, NULL); } + else + iterate_over_lwps (minus_one_ptid, resume_set_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); + /* See if it's the current inferior that should be handled + specially. */ + if (resume_many) + lp = find_lwp_pid (inferior_ptid); + else + lp = 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. */ lp->step = step; - /* Mark this LWP as resumed. */ - lp->resumed = 1; - /* If we have a pending wait status for this thread, there is no point in resuming the process. But first make sure that linux_nat_wait won't preemptively handle the event - we @@ -1613,7 +1678,7 @@ linux_nat_resume (struct target_ops *ops, int saved_signo; struct inferior *inf; - inf = find_inferior_pid (ptid_get_pid (ptid)); + inf = find_inferior_pid (ptid_get_pid (lp->ptid)); gdb_assert (inf); saved_signo = target_signal_from_host (WSTOPSIG (lp->status)); @@ -1662,8 +1727,11 @@ linux_nat_resume (struct target_ops *ops, resume_callback. */ lp->stopped = 0; - if (resume_all) - iterate_over_lwps (resume_callback, NULL); + if (resume_many) + iterate_over_lwps (ptid, resume_callback, NULL); + + /* Convert to something the lower layer understands. */ + ptid = pid_to_ptid (GET_LWP (lp->ptid)); linux_ops->to_resume (linux_ops, ptid, step, signo); memset (&lp->siginfo, 0, sizeof (lp->siginfo)); @@ -1757,7 +1825,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status, struct cleanup *old_chain; ourstatus->kind = TARGET_WAITKIND_IGNORE; - new_lp = add_lwp (BUILD_LWP (new_pid, GET_PID (inferior_ptid))); + new_lp = add_lwp (BUILD_LWP (new_pid, GET_PID (lp->ptid))); new_lp->cloned = 1; new_lp->stopped = 1; @@ -2181,7 +2249,12 @@ status_callback (struct lwp_info *lp, void *data) { /* Only report a pending wait status if we pretend that this has indeed been resumed. */ - return (lp->status != 0 && lp->resumed); + /* We check for lp->waitstatus in addition to lp->status, because we + can have pending process exits recorded in lp->waitstatus, and + W_EXITCODE(0,0) == 0. */ + return ((lp->status != 0 + || lp->waitstatus.kind != TARGET_WAITKIND_IGNORE) + && lp->resumed); } /* Return non-zero if LP isn't stopped. */ @@ -2303,7 +2376,7 @@ cancel_breakpoints_callback (struct lwp_info *lp, void *data) /* Select one LWP out of those that have events pending. */ static void -select_event_lwp (struct lwp_info **orig_lp, int *status) +select_event_lwp (ptid_t filter, struct lwp_info **orig_lp, int *status) { int num_events = 0; int random_selector; @@ -2313,7 +2386,8 @@ select_event_lwp (struct lwp_info **orig_lp, int *status) (*orig_lp)->status = *status; /* Give preference to any LWP that is being single-stepped. */ - event_lp = iterate_over_lwps (select_singlestep_lwp_callback, NULL); + event_lp = iterate_over_lwps (filter, + select_singlestep_lwp_callback, NULL); if (event_lp != NULL) { if (debug_linux_nat) @@ -2327,7 +2401,7 @@ select_event_lwp (struct lwp_info **orig_lp, int *status) which have had SIGTRAP events. */ /* First see how many SIGTRAP events we have. */ - iterate_over_lwps (count_events_callback, &num_events); + iterate_over_lwps (filter, count_events_callback, &num_events); /* Now randomly pick a LWP out of those that have had a SIGTRAP. */ random_selector = (int) @@ -2338,7 +2412,8 @@ select_event_lwp (struct lwp_info **orig_lp, int *status) "SEL: Found %d SIGTRAP events, selecting #%d\n", num_events, random_selector); - event_lp = iterate_over_lwps (select_event_lwp_callback, + event_lp = iterate_over_lwps (filter, + select_event_lwp_callback, &random_selector); } @@ -2456,7 +2531,8 @@ linux_nat_filter_event (int lwpid, int status, int options) } /* Check if the thread has exited. */ - if ((WIFEXITED (status) || WIFSIGNALED (status)) && num_lwps > 1) + if ((WIFEXITED (status) || WIFSIGNALED (status)) + && num_lwps (GET_PID (lp->ptid)) > 1) { /* If this is the main thread, we must stop all threads and verify if they are still alive. This is because in the nptl thread model @@ -2471,7 +2547,8 @@ linux_nat_filter_event (int lwpid, int status, int options) if (GET_PID (lp->ptid) == GET_LWP (lp->ptid)) { lp->stopped = 1; - iterate_over_lwps (stop_and_resume_callback, NULL); + iterate_over_lwps (pid_to_ptid (GET_PID (lp->ptid)), + stop_and_resume_callback, NULL); } if (debug_linux_nat) @@ -2479,7 +2556,7 @@ linux_nat_filter_event (int lwpid, int status, int options) "LLW: %s exited.\n", target_pid_to_str (lp->ptid)); - if (num_lwps > 1) + if (num_lwps (GET_PID (lp->ptid)) > 1) { /* If there is at least one more LWP, then the exit signal was not the end of the debugged application and should be @@ -2493,8 +2570,10 @@ linux_nat_filter_event (int lwpid, int status, int options) thread model, LWPs other than the main thread do not issue signals when they exit so we must check whenever the thread has stopped. A similar check is made in stop_wait_callback(). */ - if (num_lwps > 1 && !linux_thread_alive (lp->ptid)) + if (num_lwps (GET_PID (lp->ptid)) > 1 && !linux_thread_alive (lp->ptid)) { + ptid_t ptid = pid_to_ptid (GET_PID (lp->ptid)); + if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, "LLW: %s exited.\n", @@ -2503,7 +2582,7 @@ linux_nat_filter_event (int lwpid, int status, int options) exit_lwp (lp); /* Make sure there is at least one thread running. */ - gdb_assert (iterate_over_lwps (running_callback, NULL)); + gdb_assert (iterate_over_lwps (ptid, running_callback, NULL)); /* Discard the event. */ return NULL; @@ -2583,7 +2662,7 @@ linux_nat_wait_1 (struct target_ops *ops, struct lwp_info *lp = NULL; int options = 0; int status = 0; - pid_t pid = PIDGET (ptid); + pid_t pid; if (debug_linux_nat_async) fprintf_unfiltered (gdb_stdlog, "LLW: enter\n"); @@ -2591,10 +2670,8 @@ linux_nat_wait_1 (struct target_ops *ops, /* The first time we get here after starting a new inferior, we may not have added it to the LWP list yet - this is the earliest moment at which we know its PID. */ - if (num_lwps == 0) + if (ptid_is_pid (inferior_ptid)) { - gdb_assert (!is_lwp (inferior_ptid)); - /* Upgrade the main thread's ptid. */ thread_change_ptid (inferior_ptid, BUILD_LWP (GET_PID (inferior_ptid), @@ -2607,16 +2684,29 @@ linux_nat_wait_1 (struct target_ops *ops, /* Make sure SIGCHLD is blocked. */ block_child_signals (&prev_mask); + if (ptid_equal (ptid, minus_one_ptid)) + pid = -1; + else if (ptid_is_pid (ptid)) + /* A request to wait for a specific tgid. This is not possible + with waitpid, so instead, we wait for any child, and leave + children we're not interested in right now with a pending + status to report later. */ + pid = -1; + else + pid = GET_LWP (ptid); + retry: + lp = NULL; + status = 0; /* Make sure there is at least one LWP that has been resumed. */ - gdb_assert (iterate_over_lwps (resumed_callback, NULL)); + gdb_assert (iterate_over_lwps (ptid, resumed_callback, NULL)); /* First check if there is a LWP with a wait status pending. */ if (pid == -1) { /* Any LWP that's been resumed will do. */ - lp = iterate_over_lwps (status_callback, NULL); + lp = iterate_over_lwps (ptid, status_callback, NULL); if (lp) { status = lp->status; @@ -2658,9 +2748,16 @@ retry: the layer beneath us can understand. */ options = lp->cloned ? __WCLONE : 0; pid = GET_LWP (ptid); + + /* We check for lp->waitstatus in addition to lp->status, + because we can have pending process exits recorded in + lp->status and W_EXITCODE(0,0) == 0. We should probably have + an additional lp->status_p flag. */ + if (status == 0 && lp->waitstatus.kind == TARGET_WAITKIND_IGNORE) + lp = NULL; } - if (status && lp->signalled) + if (lp && lp->signalled) { /* A pending SIGSTOP may interfere with the normal stream of events. In a typical case where interference is a problem, @@ -2697,7 +2794,7 @@ retry: if (target_can_async_p ()) options |= WNOHANG; /* In async mode, don't block. */ - while (status == 0) + while (lp == NULL) { pid_t lwpid; @@ -2715,14 +2812,79 @@ retry: } lp = linux_nat_filter_event (lwpid, status, options); - if (!lp) + + if (lp + && ptid_is_pid (ptid) + && ptid_get_pid (lp->ptid) != ptid_get_pid (ptid)) { - /* A discarded event. */ - status = 0; + if (debug_linux_nat) + fprintf (stderr, "LWP %ld got an event %06x, leaving pending.\n", + ptid_get_lwp (lp->ptid), status); + + if (WIFSTOPPED (status)) + { + if (WSTOPSIG (status) != SIGSTOP) + { + lp->status = status; + + stop_callback (lp, NULL); + + /* Resume in order to collect the sigstop. */ + ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0); + + stop_wait_callback (lp, NULL); + } + else + { + lp->stopped = 1; + lp->signalled = 0; + } + } + else if (WIFEXITED (status) || WIFSIGNALED (status)) + { + if (debug_linux_nat) + fprintf (stderr, "Process %ld exited while stopping LWPs\n", + ptid_get_lwp (lp->ptid)); + + /* This was the last lwp in the process. Since + events are serialized to GDB core, and we can't + report this one right now, but GDB core and the + other target layers will want to be notified + about the exit code/signal, leave the status + pending for the next time we're able to report + it. */ + lp->status = status; + + /* Prevent trying to stop this thread again. We'll + never try to resume it because it has a pending + status. */ + lp->stopped = 1; + + /* Dead LWP's aren't expected to reported a pending + sigstop. */ + lp->signalled = 0; + + /* Store the pending event in the waitstatus as + well, because W_EXITCODE(0,0) == 0. */ + store_waitstatus (&lp->waitstatus, status); + } + + /* Keep looking. */ + lp = NULL; continue; } - break; + if (lp) + break; + else + { + if (pid == -1) + { + /* waitpid did return something. Restart over. */ + options |= __WCLONE; + } + continue; + } } if (pid == -1) @@ -2752,7 +2914,7 @@ retry: } /* We shouldn't end up here unless we want to try again. */ - gdb_assert (status == 0); + gdb_assert (lp == NULL); } if (!target_can_async_p ()) @@ -2801,7 +2963,6 @@ retry: target_pid_to_str (lp->ptid), signo ? strsignal (signo) : "0"); lp->stopped = 0; - status = 0; goto retry; } @@ -2817,7 +2978,8 @@ retry: will receive it - unless they're using CLONE_THREAD to share signals. Since we only want to report it once, we mark it as ignored for all LWPs except this one. */ - iterate_over_lwps (set_ignore_sigint, NULL); + iterate_over_lwps (pid_to_ptid (ptid_get_pid (ptid)), + set_ignore_sigint, NULL); lp->ignore_sigint = 0; } else @@ -2835,24 +2997,24 @@ retry: if (!non_stop) { /* Now stop all other LWP's ... */ - iterate_over_lwps (stop_callback, NULL); + iterate_over_lwps (minus_one_ptid, 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 (minus_one_ptid, stop_wait_callback, NULL); /* 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); + select_event_lwp (ptid, &lp, &status); } /* Now that we've selected our final event LWP, cancel any breakpoints in other LWPs that have hit a GDB breakpoint. See the comment in cancel_breakpoints_callback to find out why. */ - iterate_over_lwps (cancel_breakpoints_callback, lp); + iterate_over_lwps (minus_one_ptid, cancel_breakpoints_callback, lp); if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP) { @@ -3000,18 +3162,19 @@ linux_nat_kill (struct target_ops *ops) linux_fork_killall (); else { + ptid_t ptid = pid_to_ptid (ptid_get_pid (inferior_ptid)); /* Stop all threads before killing them, since ptrace requires that the thread is stopped to sucessfully PTRACE_KILL. */ - iterate_over_lwps (stop_callback, NULL); + iterate_over_lwps (ptid, 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 (ptid, stop_wait_callback, NULL); /* Kill all LWP's ... */ - iterate_over_lwps (kill_callback, NULL); + iterate_over_lwps (ptid, kill_callback, NULL); /* ... and wait until we've flushed all events. */ - iterate_over_lwps (kill_wait_callback, NULL); + iterate_over_lwps (ptid, kill_wait_callback, NULL); } target_mourn_inferior (); @@ -3020,17 +3183,11 @@ linux_nat_kill (struct target_ops *ops) static void linux_nat_mourn_inferior (struct target_ops *ops) { - /* Destroy LWP info; it's no longer valid. */ - init_lwp_list (); + purge_lwp_list (ptid_get_pid (inferior_ptid)); if (! forks_exist_p ()) - { - /* Normal case, no other forks available. */ - linux_ops->to_mourn_inferior (ops); - - if (target_can_async_p ()) - linux_nat_async (NULL, 0); - } + /* Normal case, no other forks available. */ + linux_ops->to_mourn_inferior (ops); else /* Multi-fork case. The current inferior_ptid has exited, but there are other viable forks to debug. Delete the exiting @@ -3174,8 +3331,8 @@ linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid) static char buf[64]; if (is_lwp (ptid) - && ((lwp_list && lwp_list->next) - || GET_PID (ptid) != GET_LWP (ptid))) + && (GET_PID (ptid) != GET_LWP (ptid) + || num_lwps (GET_PID (ptid)) > 1)) { snprintf (buf, sizeof (buf), "LWP %ld", GET_LWP (ptid)); return buf; @@ -3450,6 +3607,7 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size) char psargs[80] = { '\0' }; char *note_data = NULL; ptid_t current_ptid = inferior_ptid; + ptid_t filter = pid_to_ptid (ptid_get_pid (inferior_ptid)); gdb_byte *auxv; int auxv_len; @@ -3483,7 +3641,7 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size) thread_args.note_size = note_size; thread_args.num_notes = 0; thread_args.stop_signal = find_stop_signal (); - iterate_over_lwps (linux_nat_corefile_thread_callback, &thread_args); + iterate_over_lwps (filter, linux_nat_corefile_thread_callback, &thread_args); gdb_assert (thread_args.num_notes != 0); note_data = thread_args.note_data; @@ -4096,7 +4254,8 @@ linux_nat_is_async_p (void) if (!target_async_permitted) return 0; - return 1; + /* See target.h/target_async_mask. */ + return linux_nat_async_mask_value; } /* target_can_async_p implementation. */ @@ -4120,6 +4279,17 @@ linux_nat_supports_non_stop (void) return 1; } +/* True if we want to support multi-process. To be removed when GDB + supports multi-exec. */ + +int linux_multi_process = 0; + +static int +linux_nat_supports_multi_process (void) +{ + return linux_multi_process; +} + /* target_async_mask implementation. */ static int @@ -4317,56 +4487,48 @@ linux_nat_async (void (*callback) (enum inferior_event_type event_type, static int linux_nat_stop_lwp (struct lwp_info *lwp, void *data) { - ptid_t ptid = * (ptid_t *) data; - - if (ptid_equal (lwp->ptid, ptid) - || ptid_equal (minus_one_ptid, ptid) - || (ptid_is_pid (ptid) - && ptid_get_pid (ptid) == ptid_get_pid (lwp->ptid))) + if (!lwp->stopped) { - if (!lwp->stopped) - { - int pid, status; - ptid_t ptid = lwp->ptid; + int pid, status; + ptid_t ptid = lwp->ptid; - if (debug_linux_nat) - fprintf_unfiltered (gdb_stdlog, - "LNSL: running -> suspending %s\n", - target_pid_to_str (lwp->ptid)); + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "LNSL: running -> suspending %s\n", + target_pid_to_str (lwp->ptid)); - stop_callback (lwp, NULL); - stop_wait_callback (lwp, NULL); + stop_callback (lwp, NULL); + stop_wait_callback (lwp, NULL); - /* If the lwp exits while we try to stop it, there's nothing - else to do. */ - lwp = find_lwp_pid (ptid); - if (lwp == NULL) - return 0; + /* If the lwp exits while we try to stop it, there's nothing + else to do. */ + lwp = find_lwp_pid (ptid); + if (lwp == NULL) + return 0; - /* If we didn't collect any signal other than SIGSTOP while - stopping the LWP, push a SIGNAL_0 event. In either case, - the event-loop will end up calling target_wait which will - collect these. */ - if (lwp->status == 0) - lwp->status = W_STOPCODE (0); - async_file_mark (); - } - else - { - /* Already known to be stopped; do nothing. */ + /* If we didn't collect any signal other than SIGSTOP while + stopping the LWP, push a SIGNAL_0 event. In either case, the + event-loop will end up calling target_wait which will collect + these. */ + if (lwp->status == 0) + lwp->status = W_STOPCODE (0); + async_file_mark (); + } + else + { + /* Already known to be stopped; do nothing. */ - if (debug_linux_nat) - { - if (find_thread_pid (lwp->ptid)->stop_requested) - fprintf_unfiltered (gdb_stdlog, "\ + if (debug_linux_nat) + { + if (find_thread_pid (lwp->ptid)->stop_requested) + fprintf_unfiltered (gdb_stdlog, "\ LNSL: already stopped/stop_requested %s\n", - target_pid_to_str (lwp->ptid)); - else - fprintf_unfiltered (gdb_stdlog, "\ + target_pid_to_str (lwp->ptid)); + else + fprintf_unfiltered (gdb_stdlog, "\ LNSL: already stopped/no stop_requested yet %s\n", - target_pid_to_str (lwp->ptid)); - } + target_pid_to_str (lwp->ptid)); } } return 0; @@ -4376,11 +4538,25 @@ static void linux_nat_stop (ptid_t ptid) { if (non_stop) - iterate_over_lwps (linux_nat_stop_lwp, &ptid); + iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL); else linux_ops->to_stop (ptid); } +static void +linux_nat_close (int quitting) +{ + /* Unregister from the event loop. */ + if (target_is_async_p ()) + target_async (NULL, 0); + + /* Reset the async_masking. */ + linux_nat_async_mask_value = 1; + + if (linux_ops->to_close) + linux_ops->to_close (quitting); +} + void linux_nat_add_target (struct target_ops *t) { @@ -4411,10 +4587,13 @@ linux_nat_add_target (struct target_ops *t) t->to_async_mask = linux_nat_async_mask; t->to_terminal_inferior = linux_nat_terminal_inferior; t->to_terminal_ours = linux_nat_terminal_ours; + t->to_close = linux_nat_close; /* Methods for non-stop support. */ t->to_stop = linux_nat_stop; + t->to_supports_multi_process = linux_nat_supports_multi_process; + /* 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 |