• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

修订版f4836ba964a96364f39c7eab8b8b2f8656d14d05 (tree)
时间2015-12-01 03:42:33
作者Pedro Alves <palves@redh...>
CommiterPedro Alves

Log Message

infrun: Fix TARGET_WAITKIND_NO_RESUMED handling in non-stop mode

Running the testsuite against gdbserver with "maint set target-non-stop on"
stumbled on a set of problems. See code comments for details.

This handles my concerns expressed in PR14618.

gdb/ChangeLog:
2015-11-30 Pedro Alves <palves@redhat.com>

PR 14618
* infrun.c (handle_no_resumed): New function.
(handle_inferior_event_1) <TARGET_WAITKIND_NO_RESUMED>: Defer to
handle_no_resumed.

更改概述

差异

--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,12 @@
11 2015-11-30 Pedro Alves <palves@redhat.com>
22
3+ PR 14618
4+ * infrun.c (handle_no_resumed): New function.
5+ (handle_inferior_event_1) <TARGET_WAITKIND_NO_RESUMED>: Defer to
6+ handle_no_resumed.
7+
8+2015-11-30 Pedro Alves <palves@redhat.com>
9+
310 * NEWS (New commands): Mention "set/show remote thread-events"
411 commands.
512 (New remote packets): Mention thread created/exited stop reasons
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -4660,6 +4660,102 @@ stop_all_threads (void)
46604660 fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads done\n");
46614661 }
46624662
4663+/* Handle a TARGET_WAITKIND_NO_RESUMED event. */
4664+
4665+static int
4666+handle_no_resumed (struct execution_control_state *ecs)
4667+{
4668+ struct inferior *inf;
4669+ struct thread_info *thread;
4670+
4671+ if (target_can_async_p () && !sync_execution)
4672+ {
4673+ /* There were no unwaited-for children left in the target, but,
4674+ we're not synchronously waiting for events either. Just
4675+ ignore. */
4676+
4677+ if (debug_infrun)
4678+ fprintf_unfiltered (gdb_stdlog,
4679+ "infrun: TARGET_WAITKIND_NO_RESUMED " "(ignoring: bg)\n");
4680+ prepare_to_wait (ecs);
4681+ return 1;
4682+ }
4683+
4684+ /* Otherwise, if we were running a synchronous execution command, we
4685+ may need to cancel it and give the user back the terminal.
4686+
4687+ In non-stop mode, the target can't tell whether we've already
4688+ consumed previous stop events, so it can end up sending us a
4689+ no-resumed event like so:
4690+
4691+ #0 - thread 1 is left stopped
4692+
4693+ #1 - thread 2 is resumed and hits breakpoint
4694+ -> TARGET_WAITKIND_STOPPED
4695+
4696+ #2 - thread 3 is resumed and exits
4697+ this is the last resumed thread, so
4698+ -> TARGET_WAITKIND_NO_RESUMED
4699+
4700+ #3 - gdb processes stop for thread 2 and decides to re-resume
4701+ it.
4702+
4703+ #4 - gdb processes the TARGET_WAITKIND_NO_RESUMED event.
4704+ thread 2 is now resumed, so the event should be ignored.
4705+
4706+ IOW, if the stop for thread 2 doesn't end a foreground command,
4707+ then we need to ignore the following TARGET_WAITKIND_NO_RESUMED
4708+ event. But it could be that the event meant that thread 2 itself
4709+ (or whatever other thread was the last resumed thread) exited.
4710+
4711+ To address this we refresh the thread list and check whether we
4712+ have resumed threads _now_. In the example above, this removes
4713+ thread 3 from the thread list. If thread 2 was re-resumed, we
4714+ ignore this event. If we find no thread resumed, then we cancel
4715+ the synchronous command show "no unwaited-for " to the user. */
4716+ update_thread_list ();
4717+
4718+ ALL_NON_EXITED_THREADS (thread)
4719+ {
4720+ if (thread->executing
4721+ || thread->suspend.waitstatus_pending_p)
4722+ {
4723+ /* There were no unwaited-for children left in the target at
4724+ some point, but there are now. Just ignore. */
4725+ if (debug_infrun)
4726+ fprintf_unfiltered (gdb_stdlog,
4727+ "infrun: TARGET_WAITKIND_NO_RESUMED "
4728+ "(ignoring: found resumed)\n");
4729+ prepare_to_wait (ecs);
4730+ return 1;
4731+ }
4732+ }
4733+
4734+ /* Note however that we may find no resumed thread because the whole
4735+ process exited meanwhile (thus updating the thread list results
4736+ in an empty thread list). In this case we know we'll be getting
4737+ a process exit event shortly. */
4738+ ALL_INFERIORS (inf)
4739+ {
4740+ if (inf->pid == 0)
4741+ continue;
4742+
4743+ thread = any_live_thread_of_process (inf->pid);
4744+ if (thread == NULL)
4745+ {
4746+ if (debug_infrun)
4747+ fprintf_unfiltered (gdb_stdlog,
4748+ "infrun: TARGET_WAITKIND_NO_RESUMED "
4749+ "(expect process exit)\n");
4750+ prepare_to_wait (ecs);
4751+ return 1;
4752+ }
4753+ }
4754+
4755+ /* Go ahead and report the event. */
4756+ return 0;
4757+}
4758+
46634759 /* Given an execution control state that has been freshly filled in by
46644760 an event from the inferior, figure out what it means and take
46654761 appropriate action.
@@ -4704,19 +4800,8 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
47044800 }
47054801
47064802 if (ecs->ws.kind == TARGET_WAITKIND_NO_RESUMED
4707- && target_can_async_p () && !sync_execution)
4708- {
4709- /* There were no unwaited-for children left in the target, but,
4710- we're not synchronously waiting for events either. Just
4711- ignore. Otherwise, if we were running a synchronous
4712- execution command, we need to cancel it and give the user
4713- back the terminal. */
4714- if (debug_infrun)
4715- fprintf_unfiltered (gdb_stdlog,
4716- "infrun: TARGET_WAITKIND_NO_RESUMED (ignoring)\n");
4717- prepare_to_wait (ecs);
4718- return;
4719- }
4803+ && handle_no_resumed (ecs))
4804+ return;
47204805
47214806 /* Cache the last pid/waitstatus. */
47224807 set_last_target_status (ecs->ptid, ecs->ws);