/* Handling of inferior events for the event loop for GDB, the GNU debugger.
- Copyright (C) 1999, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2007, 2008, 2009 Free Software Foundation, Inc.
Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
This file is part of GDB.
#include "remote.h"
#include "exceptions.h"
#include "language.h"
+#include "gdbthread.h"
static int fetch_inferior_event_wrapper (gdb_client_data client_data);
inferior_event_handler (enum inferior_event_type event_type,
gdb_client_data client_data)
{
+ struct gdb_exception e;
int was_sync = 0;
switch (event_type)
{
case INF_ERROR:
printf_unfiltered (_("error detected from target.\n"));
- target_async (NULL, 0);
- pop_target ();
+ pop_all_targets_above (file_stratum, 0);
+ discard_all_intermediate_continuations ();
discard_all_continuations ();
async_enable_stdin ();
break;
if (!catch_errors (fetch_inferior_event_wrapper,
client_data, "", RETURN_MASK_ALL))
{
- target_async (NULL, 0);
- pop_target ();
+ pop_all_targets_above (file_stratum, 0);
+ discard_all_intermediate_continuations ();
discard_all_continuations ();
async_enable_stdin ();
display_gdb_prompt (0);
case INF_EXEC_COMPLETE:
- /* This is the first thing to do -- so that continuations know that
- the target is stopped. For example, command_line_handler_continuation
- will run breakpoint commands, and if we think that the target is
- running, we'll refuse to execute most commands. MI continuation
- presently uses target_executing to either print or not print *stopped. */
- target_executing = 0;
-
- /* Unregister the inferior from the event loop. This is done so that
- when the inferior is not running we don't get distracted by
- spurious inferior output. */
- if (target_has_execution)
- target_async (NULL, 0);
+ if (!non_stop)
+ {
+ /* Unregister the inferior from the event loop. This is done
+ so that when the inferior is not running we don't get
+ distracted by spurious inferior output. */
+ if (target_has_execution)
+ target_async (NULL, 0);
+ }
/* The call to async_enable_stdin below resets 'sync_execution'.
However, if sync_execution is 1 now, we also need to show the
was_sync = sync_execution;
async_enable_stdin ();
+ /* Do all continuations associated with the whole inferior (not
+ a particular thread). */
+ if (!ptid_equal (inferior_ptid, null_ptid))
+ do_all_inferior_continuations ();
+
/* If we were doing a multi-step (eg: step n, next n), but it
got interrupted by a breakpoint, still do the pending
continuations. The continuation itself is responsible for
- distinguishing the cases. */
- do_all_intermediate_continuations ();
-
- do_all_continuations ();
-
- if (current_language != expected_language)
+ distinguishing the cases. The continuations are allowed to
+ touch the inferior memory, e.g. to remove breakpoints, so run
+ them before running breakpoint commands, which may resume the
+ target. */
+ if (non_stop
+ && target_has_execution
+ && !ptid_equal (inferior_ptid, null_ptid))
+ do_all_intermediate_continuations_thread (inferior_thread ());
+ else
+ do_all_intermediate_continuations ();
+
+ /* Always finish the previous command before running any
+ breakpoint commands. Any stop cancels the previous command.
+ E.g. a "finish" or "step-n" command interrupted by an
+ unrelated breakpoint is canceled. */
+ if (non_stop
+ && target_has_execution
+ && !ptid_equal (inferior_ptid, null_ptid))
+ do_all_continuations_thread (inferior_thread ());
+ else
+ do_all_continuations ();
+
+ if (current_language != expected_language
+ && language_mode == language_mode_auto)
+ language_info (1); /* Print what changed. */
+
+ /* Don't propagate breakpoint commands errors. Either we're
+ stopping or some command resumes the inferior. The user will
+ be informed. */
+ TRY_CATCH (e, RETURN_MASK_ALL)
{
- if (language_mode == language_mode_auto)
- {
- language_info (1); /* Print what changed. */
- }
+ bpstat_do_actions ();
}
- /* If the continuation did not start the target again,
- prepare for interation with the user. */
- if (!target_executing)
- {
- if (was_sync)
- {
- display_gdb_prompt (0);
- }
- else
- {
- if (exec_done_display_p)
- printf_unfiltered (_("completed.\n"));
- }
- }
+ if (!was_sync && !is_running (inferior_ptid) && exec_done_display_p)
+ printf_unfiltered (_("completed.\n"));
break;
case INF_EXEC_CONTINUE:
/* Is there anything left to do for the command issued to
complete? */
- do_all_intermediate_continuations ();
+
+ if (non_stop)
+ do_all_intermediate_continuations_thread (inferior_thread ());
+ else
+ do_all_intermediate_continuations ();
break;
case INF_QUIT_REQ: