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.
This commit is contained in:
Pedro Alves
2011-10-28 18:30:00 +00:00
parent b3f5b73ba4
commit 0e5bf2a8c9
15 changed files with 959 additions and 125 deletions

View File

@ -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)