diff options
author | Pedro Alves <palves@redhat.com> | 2011-10-28 18:30:00 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2011-10-28 18:30:00 +0000 |
commit | 0e5bf2a8c930b383586bcf0476859e55571da0c7 (patch) | |
tree | eee0d9cec99152019ae18207c37a54bdc649b6f9 /gdb/infrun.c | |
parent | b3f5b73ba4972d7d2b1456afe78e1c5a5540371b (diff) | |
download | fsf-binutils-gdb-0e5bf2a8c930b383586bcf0476859e55571da0c7.zip fsf-binutils-gdb-0e5bf2a8c930b383586bcf0476859e55571da0c7.tar.gz fsf-binutils-gdb-0e5bf2a8c930b383586bcf0476859e55571da0c7.tar.bz2 |
2011-10-28 Pedro Alves <pedro@codesourcery.com>
gdb/
* linux-nat.c (linux_nat_filter_event): Remove `options'
parameter, and dead code that used it. If we're handling a
PTRACE_EVENT_EXEC event, and the thread group leader is no longer
in our lwp list, re-add it.
(check_zombie_leaders): New.
(linux_nat_wait_1): Remove `options' and `pid' locals. Always
wait for children with WNOHANG, and always wait for all children.
Don't check for no resumed children upfront. Simplify wait loop.
Check for zombie thread group leaders after handling all wait
statuses. Return TARGET_WAITKIND_NO_RESUMED if there no
unwaited-for children left.
* infrun.c (fetch_inferior_event): Handle TARGET_WAITKIND_NO_RESUMED.
(handle_inferior_event): Handle TARGET_WAITKIND_NO_RESUMED.
(normal_stop): Handle TARGET_WAITKIND_NO_RESUMED.
* target.h (enum target_waitkind) <TARGET_WAITKIND_NO_RESUMED>: New.
gdb/testsuite/
* gdb.threads/no-unwaited-for-left.c: New.
* gdb.threads/no-unwaited-for-left.exp: New.
* gdb.threads/non-ldr-exc-1.c: New.
* gdb.threads/non-ldr-exc-1.exp: New.
* gdb.threads/non-ldr-exc-2.c: New.
* gdb.threads/non-ldr-exc-2.exp: New.
* gdb.threads/non-ldr-exc-3.c: New.
* gdb.threads/non-ldr-exc-3.exp: New.
* gdb.threads/non-ldr-exc-4.c: New.
* gdb.threads/non-ldr-exc-4.exp: New.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index ac2b5ae..e0c59a1 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -2773,6 +2773,7 @@ fetch_inferior_event (void *client_data) if (non_stop && ecs->ws.kind != TARGET_WAITKIND_IGNORE + && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED && ecs->ws.kind != TARGET_WAITKIND_EXITED && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED) /* In non-stop mode, each thread is handled individually. Switch @@ -2806,6 +2807,7 @@ fetch_inferior_event (void *client_data) normal_stop (); if (target_has_execution + && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED && ecs->ws.kind != TARGET_WAITKIND_EXITED && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED && ecs->event_thread->step_multi @@ -3164,8 +3166,24 @@ handle_inferior_event (struct execution_control_state *ecs) return; } + if (ecs->ws.kind == TARGET_WAITKIND_NO_RESUMED + && target_can_async_p () && !sync_execution) + { + /* There were no unwaited-for children left in the target, but, + we're not synchronously waiting for events either. Just + ignore. Otherwise, if we were running a synchronous + execution command, we need to cancel it and give the user + back the terminal. */ + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: TARGET_WAITKIND_NO_RESUMED (ignoring)\n"); + prepare_to_wait (ecs); + return; + } + if (ecs->ws.kind != TARGET_WAITKIND_EXITED - && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED) + && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED + && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED) { struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid)); @@ -3182,6 +3200,18 @@ handle_inferior_event (struct execution_control_state *ecs) /* Always clear state belonging to the previous time we stopped. */ stop_stack_dummy = STOP_NONE; + if (ecs->ws.kind == TARGET_WAITKIND_NO_RESUMED) + { + /* No unwaited-for children left. IOW, all resumed children + have exited. */ + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_NO_RESUMED\n"); + + stop_print_frame = 0; + stop_stepping (ecs); + return; + } + /* If it's a new process, add it to the thread database. */ ecs->new_thread_event = (!ptid_equal (ecs->ptid, inferior_ptid) @@ -5824,7 +5854,8 @@ normal_stop (void) if (!non_stop) make_cleanup (finish_thread_state_cleanup, &minus_one_ptid); else if (last.kind != TARGET_WAITKIND_SIGNALLED - && last.kind != TARGET_WAITKIND_EXITED) + && last.kind != TARGET_WAITKIND_EXITED + && last.kind != TARGET_WAITKIND_NO_RESUMED) make_cleanup (finish_thread_state_cleanup, &inferior_ptid); /* In non-stop mode, we don't want GDB to switch threads behind the @@ -5843,7 +5874,8 @@ normal_stop (void) && !ptid_equal (previous_inferior_ptid, inferior_ptid) && target_has_execution && last.kind != TARGET_WAITKIND_SIGNALLED - && last.kind != TARGET_WAITKIND_EXITED) + && last.kind != TARGET_WAITKIND_EXITED + && last.kind != TARGET_WAITKIND_NO_RESUMED) { target_terminal_ours_for_output (); printf_filtered (_("[Switching to %s]\n"), @@ -5852,6 +5884,14 @@ normal_stop (void) previous_inferior_ptid = inferior_ptid; } + if (last.kind == TARGET_WAITKIND_NO_RESUMED) + { + gdb_assert (sync_execution || !target_can_async_p ()); + + target_terminal_ours_for_output (); + printf_filtered (_("No unwaited-for children left.\n")); + } + if (!breakpoints_always_inserted_mode () && target_has_execution) { if (remove_breakpoints ()) @@ -6038,6 +6078,7 @@ done: if (!target_has_execution || last.kind == TARGET_WAITKIND_SIGNALLED || last.kind == TARGET_WAITKIND_EXITED + || last.kind == TARGET_WAITKIND_NO_RESUMED || (!inferior_thread ()->step_multi && !(inferior_thread ()->control.stop_bpstat && inferior_thread ()->control.proceed_to_finish) |