aboutsummaryrefslogtreecommitdiff
path: root/gdb/inf-loop.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2014-07-14 19:55:32 +0100
committerPedro Alves <palves@redhat.com>2014-07-14 20:34:23 +0100
commit1e9735707b34b8141ea3bfd88205ea26e99891fc (patch)
tree62ba3c6b7851fa9438c6d5b2e4fea830e69621f9 /gdb/inf-loop.c
parent93d6eb10ede1d8b72b274345c63f66439eaf7fd0 (diff)
downloadgdb-1e9735707b34b8141ea3bfd88205ea26e99891fc.zip
gdb-1e9735707b34b8141ea3bfd88205ea26e99891fc.tar.gz
gdb-1e9735707b34b8141ea3bfd88205ea26e99891fc.tar.bz2
Fix double prompt
If an error is thrown while handling a target event (within fetch_inferior_event), and, the interpreter is not async (but the target is), then GDB prints the prompt twice. One way to see that in action is throw a QUIT while in a pagination prompt issued from within fetch_inferior_event (or one of its callees). E.g. from the test: ---Type <return> to continue, or q <return> to quit--- ^CQuit (gdb) (gdb) p 1 ^^^^^^^^^^^ $1 = 1 (gdb) The issue is that inferior_event_handler swallows errors and notifies the observers (the interpreters) about the command error, even if the interpreter is forced sync while we're handling a nested event loop (for execute_command). The observers print a prompt, and then when we get back to the top event loop, we print another (in start_event_loop). I see no reason the error should be swallowed here. Just cancel the execution related bits and let the error propagate to the top level (start_event_loop), which re-enables stdin and notifies observers. gdb/ 2014-07-14 Pedro Alves <palves@redhat.com> * inf-loop.c (inferior_event_handler): Use TRY_CATCH instead of catch_errors. Don't re-enable stdin or notify observers where, and rethrow error. (fetch_inferior_event_wrapper): Delete. gdb/testsuite/ 2014-07-14 Pedro Alves <palves@redhat.com> * gdb.base/double-prompt-target-event-error.c: New file. * gdb.base/double-prompt-target-event-error.exp: New file.
Diffstat (limited to 'gdb/inf-loop.c')
-rw-r--r--gdb/inf-loop.c36
1 files changed, 17 insertions, 19 deletions
diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c
index 247e9d6..d4f9a35 100644
--- a/gdb/inf-loop.c
+++ b/gdb/inf-loop.c
@@ -33,8 +33,6 @@
#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
@@ -48,19 +46,26 @@ inferior_event_handler (enum inferior_event_type event_type,
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:
@@ -140,10 +145,3 @@ inferior_event_handler (enum inferior_event_type event_type,
discard_cleanups (cleanup_if_error);
}
-
-static int
-fetch_inferior_event_wrapper (gdb_client_data client_data)
-{
- fetch_inferior_event (client_data);
- return 1;
-}