#include "top.h"
#include "observer.h"
-static int fetch_inferior_event_wrapper (gdb_client_data client_data);
-
/* General function to handle events in the inferior. So far it just
takes care of detecting errors reported by select() or poll(),
otherwise it assumes that all is OK, and goes on reading data from
switch (event_type)
{
case INF_REG_EVENT:
- /* Use catch errors for now, until the inner layers of
+ /* Catch errors for now, until the inner layers of
fetch_inferior_event (i.e. readchar) can return meaningful
error status. If an error occurs while getting an event from
the target, just cancel the current command. */
- if (!catch_errors (fetch_inferior_event_wrapper,
- client_data, "", RETURN_MASK_ALL))
- {
- bpstat_clear_actions ();
- do_all_intermediate_continuations (1);
- do_all_continuations (1);
- async_enable_stdin ();
- observer_notify_command_error ();
- }
+ {
+ volatile struct gdb_exception ex;
+
+ TRY_CATCH (ex, RETURN_MASK_ALL)
+ {
+ fetch_inferior_event (client_data);
+ }
+ if (ex.reason < 0)
+ {
+ bpstat_clear_actions ();
+ do_all_intermediate_continuations (1);
+ do_all_continuations (1);
+
+ throw_exception (ex);
+ }
+ }
break;
case INF_EXEC_COMPLETE:
discard_cleanups (cleanup_if_error);
}
-
-static int
-fetch_inferior_event_wrapper (gdb_client_data client_data)
-{
- fetch_inferior_event (client_data);
- return 1;
-}
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+
+int
+main (void)
+{
+ sleep (3);
+ return 0; /* after sleep */
+}
--- /dev/null
+# Copyright (C) 2014 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug] == -1} {
+ return -1
+}
+
+# Test throwing an error while GDB is handling a target event. We use
+# a ctrl-c/quit in a pagination prompt to emulate an error. COMMAND
+# is either "continue" or "wrapcont". The latter is a continue issued
+# from a user-defined command. That exercises the case of the
+# interpreter forced sync, which was the case that originally had a
+# bug.
+
+proc cancel_pagination_in_target_event { command } {
+ global binfile srcfile
+ global gdb_prompt pagination_prompt
+
+ set testline [gdb_get_line_number "after sleep"]
+
+ with_test_prefix "ctrlc target event: $command" {
+ clean_restart $binfile
+
+ if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+ }
+
+ gdb_test "b $srcfile:$testline" \
+ "Breakpoint .*$srcfile, line $testline.*" \
+ "set breakpoint"
+
+ gdb_test_no_output "set height 2"
+
+ if { $command == "wrapcont" } {
+ gdb_test_multiple "define wrapcont" "define user command: wrapcont" {
+ -re "Type commands for definition of \"wrapcont\".\r\nEnd with a line saying just \"end\".\r\n>$" {
+ # Note that "Continuing." is ommitted when
+ # "continue" is issued from a user-defined
+ # command. Issue it ourselves.
+ gdb_test "echo Continuing\.\ncontinue\nend" "" \
+ "define user command: wrapcont"
+ }
+ }
+ }
+
+ # Wait for pagination prompt after the "Continuing" line,
+ # indicating the program was running and then stopped.
+ set saw_continuing 0
+ set test "continue to pagination"
+ gdb_test_multiple "$command" $test {
+ -re "$pagination_prompt$" {
+ if {$saw_continuing} {
+ pass $test
+ } else {
+ send_gdb "\n"
+ exp_continue
+ }
+ }
+ -re "Continuing" {
+ set saw_continuing 1
+ exp_continue
+ }
+ -notransfer -re "<return>" {
+ # Otherwise gdb_test_multiple considers this an error.
+ exp_continue
+ }
+ }
+
+ # We're now stopped in a pagination query while handling a
+ # target event (printing where the program stopped). Quitting
+ # the pagination should result in only one prompt being
+ # output.
+ send_gdb "\003p 1\n"
+
+ set test "no double prompt"
+ gdb_test_multiple "" $test {
+ -re "$gdb_prompt.*$gdb_prompt.*$gdb_prompt $" {
+ fail $test
+ }
+ -re "$gdb_prompt .* = 1\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -notransfer -re "<return>" {
+ # Otherwise gdb_test_multiple considers this an error.
+ exp_continue
+ }
+ }
+
+ # In case the board file wants to send further commands.
+ gdb_test_no_output "set height unlimited"
+ }
+}
+
+foreach variant { "continue" "wrapcont" } {
+ cancel_pagination_in_target_event $variant
+}