修订版 | f4836ba964a96364f39c7eab8b8b2f8656d14d05 (tree) |
---|---|
时间 | 2015-12-01 03:42:33 |
作者 | Pedro Alves <palves@redh...> |
Commiter | Pedro Alves |
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.
@@ -1,5 +1,12 @@ | ||
1 | 1 | 2015-11-30 Pedro Alves <palves@redhat.com> |
2 | 2 | |
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 | + | |
3 | 10 | * NEWS (New commands): Mention "set/show remote thread-events" |
4 | 11 | commands. |
5 | 12 | (New remote packets): Mention thread created/exited stop reasons |
@@ -4660,6 +4660,102 @@ stop_all_threads (void) | ||
4660 | 4660 | fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads done\n"); |
4661 | 4661 | } |
4662 | 4662 | |
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 | + | |
4663 | 4759 | /* Given an execution control state that has been freshly filled in by |
4664 | 4760 | an event from the inferior, figure out what it means and take |
4665 | 4761 | appropriate action. |
@@ -4704,19 +4800,8 @@ handle_inferior_event_1 (struct execution_control_state *ecs) | ||
4704 | 4800 | } |
4705 | 4801 | |
4706 | 4802 | 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; | |
4720 | 4805 | |
4721 | 4806 | /* Cache the last pid/waitstatus. */ |
4722 | 4807 | set_last_target_status (ecs->ptid, ecs->ws); |