aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog53
-rw-r--r--gdb/breakpoint.c84
-rw-r--r--gdb/breakpoint.h2
-rw-r--r--gdb/defs.h13
-rw-r--r--gdb/exceptions.c6
-rw-r--r--gdb/inf-loop.c10
-rw-r--r--gdb/infcmd.c145
-rw-r--r--gdb/infrun.c9
-rw-r--r--gdb/interps.c2
-rw-r--r--gdb/mi/mi-interp.c5
-rw-r--r--gdb/mi/mi-main.c64
-rw-r--r--gdb/top.c5
-rw-r--r--gdb/utils.c25
13 files changed, 219 insertions, 204 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 806173c..58c0454 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,58 @@
2008-04-24 Vladimir Prus <vladimir@codesourcery.com>
+ exec_cleanup murder.
+ * breakpoint.c (until_break_command_continuation): Add
+ the 'error' parameter. Directly delete the breakoint as
+ opposed to running cleanups.
+ (until_break_command): Install continuation only
+ after starting the target. Don't use exec cleanups,
+ use ordinary cleanups. Discard cleanups is successfully
+ started the target in async mode.
+ (make_cleanup_delete_breakpoint): Remove.
+ * breakpoint.h (make_cleanup_delete_breakpoint): Remove
+ declaration.
+ * defs.h (do_exec_cleanups, make_exec_cleanup): Remove
+ declarations.
+ (struct continations): Add the 'error' parameter to the
+ continuation_hook field.
+ (add_continuation, do_all_continuations)
+ (add_intermediate_continuation)
+ (do_all_intermediate_continuations): Add the 'error' parameter.
+ * exceptions.c (throw_exception): Don't call do_exec_cleanups.
+ * inf-loop.c (inferior_event_handler): Instead of calling
+ discard_all_continuations, use do_all_continuations with 1 as
+ 'error' parameter. Pass 0 as 'error' parameter in existing uses
+ of discard_all_continuations.
+ * infcmd.c (step_1): Do not use exec cleanup. For async case, discard
+ cleanups.
+ (step_once): Install continuation only after resuming the target.
+ (step_1_continuation): Disable longjmp breakpoint on error.
+ (finish_command_continuation): Add the error parameter. Delete
+ the finish breakpoint directly, do not use cleanups.
+ (finish_command): Do not use exec_cleanups. Always setup
+ continuation. For sync case, immediately run them.
+ (attach_command_continuation): Add the error parameter.
+ * infrun.c (fetch_inferior_event): Do not use exec cleanups to
+ remove step_resume_breakpoint -- adjust delete it directly.
+ * interps.c (interp_set): Adjust call to do_all_continations.
+ * mi/mi-interp.c (mi_interpreter_exec_continuation): Do not
+ do exec cleanups.
+ * mi/mi-main.c (mi_cmd_target_select): Do not do exec
+ cleanups.
+ (mi_cmd_execute): Do not use exec_cleanup.
+ (mi_execute_async_cli_command): Simplify the string concatenation
+ logic. Do no use exec cleanup.
+ (mi_exec_async_cli_cmd_continuation): New parameter error.
+ Free last_async_command.
+ * top.c (command_line_handler_continuation): New parameter error.
+ * utils.c (exec_cleanup_chain, make_exec_cleanup)
+ (do_exec_cleanups): Remove.
+ (add_continuation, do_all_continations)
+ (add_intermediate_continuation)
+ (do_all_intermediate_continuations): New parameter error.
+
+2008-04-24 Vladimir Prus <vladimir@codesourcery.com>
+
* breakpoint.h (bp_location_p): New typedef.
Register a vector of bp_location_p.
* breakpoint.c (always_inserted_mode)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 84802ef..2b6e16f 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -64,7 +64,8 @@
/* Prototypes for local functions. */
-static void until_break_command_continuation (struct continuation_arg *arg);
+static void until_break_command_continuation (struct continuation_arg *arg,
+ int error);
static void catch_command_1 (char *, int, int);
@@ -6130,12 +6131,11 @@ awatch_command (char *arg, int from_tty)
care of cleaning up the temporary breakpoints set up by the until
command. */
static void
-until_break_command_continuation (struct continuation_arg *arg)
+until_break_command_continuation (struct continuation_arg *arg, int error)
{
- struct cleanup *cleanups;
-
- cleanups = (struct cleanup *) arg->data.pointer;
- do_exec_cleanups (cleanups);
+ delete_breakpoint ((struct breakpoint *)(arg->data.pointer));
+ if (arg->next)
+ delete_breakpoint ((struct breakpoint *)(arg->next->data.pointer));
}
void
@@ -6146,8 +6146,10 @@ until_break_command (char *arg, int from_tty, int anywhere)
struct frame_info *frame = get_selected_frame (NULL);
struct frame_info *prev_frame = get_prev_frame (frame);
struct breakpoint *breakpoint;
+ struct breakpoint *breakpoint2 = NULL;
struct cleanup *old_chain;
struct continuation_arg *arg1;
+ struct continuation_arg *arg2;
clear_proceed_status ();
@@ -6183,31 +6185,7 @@ until_break_command (char *arg, int from_tty, int anywhere)
breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame),
bp_until);
- if (!target_can_async_p ())
- old_chain = make_cleanup_delete_breakpoint (breakpoint);
- else
- old_chain = make_exec_cleanup_delete_breakpoint (breakpoint);
-
- /* If we are running asynchronously, and the target supports async
- execution, we are not waiting for the target to stop, in the call
- tp proceed, below. This means that we cannot delete the
- brekpoints until the target has actually stopped. The only place
- where we get a chance to do that is in fetch_inferior_event, so
- we must set things up for that. */
-
- if (target_can_async_p ())
- {
- /* In this case the arg for the continuation is just the point
- in the exec_cleanups chain from where to start doing
- cleanups, because all the continuation does is the cleanups in
- the exec_cleanup_chain. */
- arg1 =
- (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
- arg1->next = NULL;
- arg1->data.pointer = old_chain;
-
- add_continuation (until_break_command_continuation, arg1);
- }
+ old_chain = make_cleanup_delete_breakpoint (breakpoint);
/* Keep within the current frame, or in frames called by the current
one. */
@@ -6215,18 +6193,38 @@ until_break_command (char *arg, int from_tty, int anywhere)
{
sal = find_pc_line (get_frame_pc (prev_frame), 0);
sal.pc = get_frame_pc (prev_frame);
- breakpoint = set_momentary_breakpoint (sal, get_frame_id (prev_frame),
- bp_until);
- if (!target_can_async_p ())
- make_cleanup_delete_breakpoint (breakpoint);
- else
- make_exec_cleanup_delete_breakpoint (breakpoint);
+ breakpoint2 = set_momentary_breakpoint (sal, get_frame_id (prev_frame),
+ bp_until);
+ make_cleanup_delete_breakpoint (breakpoint2);
}
proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
- /* Do the cleanups now, anly if we are not running asynchronously,
- of if we are, but the target is still synchronous. */
- if (!target_can_async_p ())
+
+ /* If we are running asynchronously, and proceed call above has actually
+ managed to start the target, arrange for breakpoints to be
+ deleted when the target stops. Otherwise, we're already stopped and
+ delete breakpoints via cleanup chain. */
+
+ if (target_can_async_p () && target_executing)
+ {
+ arg1 =
+ (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+ arg1->next = NULL;
+ arg1->data.pointer = breakpoint;
+
+ if (breakpoint2)
+ {
+ arg2 = (struct continuation_arg *)
+ xmalloc ( sizeof (struct continuation_arg));
+ arg2->next = NULL;
+ arg2->data.pointer = breakpoint2;
+ arg1->next = arg2;
+ }
+
+ discard_cleanups (old_chain);
+ add_continuation (until_break_command_continuation, arg1);
+ }
+ else
do_cleanups (old_chain);
}
@@ -7188,12 +7186,6 @@ make_cleanup_delete_breakpoint (struct breakpoint *b)
return make_cleanup (do_delete_breakpoint_cleanup, b);
}
-struct cleanup *
-make_exec_cleanup_delete_breakpoint (struct breakpoint *b)
-{
- return make_exec_cleanup (do_delete_breakpoint_cleanup, b);
-}
-
void
delete_command (char *arg, int from_tty)
{
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index ed76f30..83f1cb8 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -700,8 +700,6 @@ extern void breakpoint_init_inferior (enum inf_context);
extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *);
-extern struct cleanup *make_exec_cleanup_delete_breakpoint (struct breakpoint *);
-
extern void delete_breakpoint (struct breakpoint *);
extern void breakpoint_auto_delete (bpstat);
diff --git a/gdb/defs.h b/gdb/defs.h
index 2ec9199..2af40ab 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -318,7 +318,6 @@ extern char *safe_strerror (int);
extern void do_cleanups (struct cleanup *);
extern void do_final_cleanups (struct cleanup *);
-extern void do_exec_cleanups (struct cleanup *);
extern void discard_cleanups (struct cleanup *);
extern void discard_final_cleanups (struct cleanup *);
@@ -351,8 +350,6 @@ extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *);
extern struct cleanup *make_my_cleanup (struct cleanup **,
make_cleanup_ftype *, void *);
-extern struct cleanup *make_exec_cleanup (make_cleanup_ftype *, void *);
-
extern struct cleanup *save_cleanups (void);
extern struct cleanup *save_final_cleanups (void);
extern struct cleanup *save_my_cleanups (struct cleanup **);
@@ -682,7 +679,7 @@ struct continuation_arg
struct continuation
{
- void (*continuation_hook) (struct continuation_arg *);
+ void (*continuation_hook) (struct continuation_arg *, int);
struct continuation_arg *arg_list;
struct continuation *next;
};
@@ -693,14 +690,14 @@ extern struct continuation *cmd_continuation;
extern struct continuation *intermediate_continuation;
/* From utils.c */
-extern void add_continuation (void (*)(struct continuation_arg *),
+extern void add_continuation (void (*)(struct continuation_arg *, int),
struct continuation_arg *);
-extern void do_all_continuations (void);
+extern void do_all_continuations (int error);
extern void discard_all_continuations (void);
-extern void add_intermediate_continuation (void (*)(struct continuation_arg *),
+extern void add_intermediate_continuation (void (*)(struct continuation_arg *, int),
struct continuation_arg *);
-extern void do_all_intermediate_continuations (void);
+extern void do_all_intermediate_continuations (int error);
extern void discard_all_intermediate_continuations (void);
/* String containing the current directory (what getwd would return). */
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index 89d1455..304c8c6 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -221,12 +221,6 @@ throw_exception (struct gdb_exception exception)
disable_current_display ();
do_cleanups (ALL_CLEANUPS);
- /* When we implement non-stop mode, this should be redone. If we get
- exception in a command pertaining to one thread, or maybe even not
- involving inferior at all, we should not do exec cleanups for all
- threads. */
- if (target_can_async_p () && !target_executing)
- do_exec_cleanups (ALL_CLEANUPS);
/* Jump to the containing catch_errors() call, communicating REASON
to that call via setjmp's return value. Note that REASON can't
diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c
index 9519c79..4c61dae 100644
--- a/gdb/inf-loop.c
+++ b/gdb/inf-loop.c
@@ -50,7 +50,7 @@ inferior_event_handler (enum inferior_event_type event_type,
printf_unfiltered (_("error detected from target.\n"));
target_async (NULL, 0);
pop_target ();
- discard_all_continuations ();
+ do_all_continuations (1);
async_enable_stdin ();
break;
@@ -64,7 +64,7 @@ inferior_event_handler (enum inferior_event_type event_type,
{
target_async (NULL, 0);
pop_target ();
- discard_all_continuations ();
+ do_all_continuations (1);
async_enable_stdin ();
display_gdb_prompt (0);
}
@@ -95,9 +95,9 @@ inferior_event_handler (enum inferior_event_type event_type,
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_intermediate_continuations (0);
- do_all_continuations ();
+ do_all_continuations (0);
if (current_language != expected_language)
{
@@ -126,7 +126,7 @@ inferior_event_handler (enum inferior_event_type event_type,
case INF_EXEC_CONTINUE:
/* Is there anything left to do for the command issued to
complete? */
- do_all_intermediate_continuations ();
+ do_all_intermediate_continuations (0);
break;
case INF_QUIT_REQ:
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 22a4abb..867dadf 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -72,7 +72,8 @@ static void nofp_registers_info (char *, int);
static void print_return_value (struct type *func_type,
struct type *value_type);
-static void finish_command_continuation (struct continuation_arg *);
+static void finish_command_continuation (struct continuation_arg *,
+ int error_p);
static void until_next_command (int);
@@ -106,7 +107,7 @@ static void jump_command (char *, int);
static void step_1 (int, int, char *);
static void step_once (int skip_subroutines, int single_inst, int count);
-static void step_1_continuation (struct continuation_arg *arg);
+static void step_1_continuation (struct continuation_arg *arg, int error_p);
static void next_command (char *, int);
@@ -701,7 +702,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
{
int count = 1;
struct frame_info *frame;
- struct cleanup *cleanups = 0;
+ struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
int async_exec = 0;
ERROR_NO_INFERIOR;
@@ -727,10 +728,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
if (!single_inst || skip_subroutines) /* leave si command alone */
{
enable_longjmp_breakpoint ();
- if (!target_can_async_p ())
- cleanups = make_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/);
- else
- make_exec_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/);
+ make_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/);
}
/* In synchronous case, all is well, just use the regular for loop. */
@@ -782,8 +780,7 @@ which has no line number information.\n"), name);
break;
}
- if (!single_inst || skip_subroutines)
- do_cleanups (cleanups);
+ do_cleanups (cleanups);
return;
}
/* In case of asynchronous target things get complicated, do only
@@ -792,8 +789,10 @@ which has no line number information.\n"), name);
and handle them one at the time, through step_once(). */
else
{
- if (target_can_async_p ())
- step_once (skip_subroutines, single_inst, count);
+ step_once (skip_subroutines, single_inst, count);
+ /* We are running, and the contination is installed. It will
+ disable the longjmp breakpoint as appropriate. */
+ discard_cleanups (cleanups);
}
}
@@ -803,21 +802,26 @@ which has no line number information.\n"), name);
proceed(), via step_once(). Basically it is like step_once and
step_1_continuation are co-recursive. */
static void
-step_1_continuation (struct continuation_arg *arg)
+step_1_continuation (struct continuation_arg *arg, int error_p)
{
- int count;
- int skip_subroutines;
- int single_inst;
-
- skip_subroutines = arg->data.integer;
- single_inst = arg->next->data.integer;
- count = arg->next->next->data.integer;
-
- if (stop_step)
- step_once (skip_subroutines, single_inst, count - 1);
+ if (error_p)
+ disable_longjmp_breakpoint ();
else
- if (!single_inst || skip_subroutines)
- do_exec_cleanups (ALL_CLEANUPS);
+ {
+ int count;
+ int skip_subroutines;
+ int single_inst;
+
+ skip_subroutines = arg->data.integer;
+ single_inst = arg->next->data.integer;
+ count = arg->next->next->data.integer;
+
+ if (stop_step)
+ step_once (skip_subroutines, single_inst, count - 1);
+ else
+ if (!single_inst || skip_subroutines)
+ disable_longjmp_breakpoint ();
+ }
}
/* Do just one step operation. If count >1 we will have to set up a
@@ -881,6 +885,7 @@ which has no line number information.\n"), name);
step_over_calls = STEP_OVER_ALL;
step_multi = (count > 1);
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
arg1 =
(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
arg2 =
@@ -894,7 +899,6 @@ which has no line number information.\n"), name);
arg3->next = NULL;
arg3->data.integer = count;
add_intermediate_continuation (step_1_continuation, arg1);
- proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
}
}
@@ -1251,7 +1255,7 @@ print_return_value (struct type *func_type, struct type *value_type)
called via the cmd_continuation pointer. */
static void
-finish_command_continuation (struct continuation_arg *arg)
+finish_command_continuation (struct continuation_arg *arg, int error_p)
{
struct symbol *function;
struct breakpoint *breakpoint;
@@ -1261,21 +1265,24 @@ finish_command_continuation (struct continuation_arg *arg)
function = (struct symbol *) arg->next->data.pointer;
cleanups = (struct cleanup *) arg->next->next->data.pointer;
- if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
- && function != NULL)
+ if (!error_p)
{
- struct type *value_type;
-
- value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
- if (!value_type)
- internal_error (__FILE__, __LINE__,
- _("finish_command: function has no target type"));
-
- if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
- print_return_value (SYMBOL_TYPE (function), value_type);
+ if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
+ && function != NULL)
+ {
+ struct type *value_type;
+
+ value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
+ if (!value_type)
+ internal_error (__FILE__, __LINE__,
+ _("finish_command: function has no target type"));
+
+ if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
+ print_return_value (SYMBOL_TYPE (function), value_type);
+ }
}
- do_exec_cleanups (cleanups);
+ delete_breakpoint (breakpoint);
}
/* "finish": Set a temporary breakpoint at the place the selected
@@ -1326,10 +1333,7 @@ finish_command (char *arg, int from_tty)
breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), bp_finish);
- if (!target_can_async_p ())
- old_chain = make_cleanup_delete_breakpoint (breakpoint);
- else
- old_chain = make_exec_cleanup_delete_breakpoint (breakpoint);
+ old_chain = make_cleanup_delete_breakpoint (breakpoint);
/* Find the function we will return from. */
@@ -1346,51 +1350,26 @@ finish_command (char *arg, int from_tty)
proceed_to_finish = 1; /* We want stop_registers, please... */
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
- /* If running asynchronously and the target support asynchronous
- execution, set things up for the rest of the finish command to be
- completed later on, when gdb has detected that the target has
- stopped, in fetch_inferior_event.
- Setup it only after proceed, so that if proceed throws, we don't
- set continuation. */
- if (target_can_async_p ())
- {
- arg1 =
- (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
- arg2 =
- (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
- arg3 =
- (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
- arg1->next = arg2;
- arg2->next = arg3;
- arg3->next = NULL;
- arg1->data.pointer = breakpoint;
- arg2->data.pointer = function;
- arg3->data.pointer = old_chain;
- add_continuation (finish_command_continuation, arg1);
- }
+ arg1 =
+ (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+ arg2 =
+ (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+ arg3 =
+ (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+ arg1->next = arg2;
+ arg2->next = arg3;
+ arg3->next = NULL;
+ arg1->data.pointer = breakpoint;
+ arg2->data.pointer = function;
+ arg3->data.pointer = old_chain;
+ add_continuation (finish_command_continuation, arg1);
/* Do this only if not running asynchronously or if the target
cannot do async execution. Otherwise, complete this command when
the target actually stops, in fetch_inferior_event. */
+ discard_cleanups (old_chain);
if (!target_can_async_p ())
- {
- /* Did we stop at our breakpoint? */
- if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
- && function != NULL)
- {
- struct type *value_type;
-
- value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
- if (!value_type)
- internal_error (__FILE__, __LINE__,
- _("finish_command: function has no target type"));
-
- if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
- print_return_value (SYMBOL_TYPE (function), value_type);
- }
-
- do_cleanups (old_chain);
- }
+ do_all_continuations (0);
}
@@ -1936,7 +1915,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
}
static void
-attach_command_continuation (struct continuation_arg *arg)
+attach_command_continuation (struct continuation_arg *arg, int error_p)
{
char *args;
int from_tty;
diff --git a/gdb/infrun.c b/gdb/infrun.c
index da8c3e0..e47cf1e 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1073,9 +1073,6 @@ fetch_inferior_event (void *client_data)
if (!async_ecs->wait_some_more)
{
- old_cleanups = make_exec_cleanup (delete_step_resume_breakpoint,
- &step_resume_breakpoint);
-
/* Fill in with reasonable starting values. */
init_execution_control_state (async_ecs);
@@ -1104,10 +1101,8 @@ fetch_inferior_event (void *client_data)
if (!async_ecs->wait_some_more)
{
- /* Do only the cleanups that have been added by this
- function. Let the continuations for the commands do the rest,
- if there are any. */
- do_exec_cleanups (old_cleanups);
+ delete_step_resume_breakpoint (&step_resume_breakpoint);
+
normal_stop ();
if (step_multi && stop_step)
inferior_event_handler (INF_EXEC_CONTINUE, NULL);
diff --git a/gdb/interps.c b/gdb/interps.c
index b4c804a..0ebc3f4 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -148,7 +148,7 @@ interp_set (struct interp *interp, int top_level)
if (current_interpreter != NULL)
{
- do_all_continuations ();
+ do_all_continuations (0);
ui_out_flush (uiout);
if (current_interpreter->procs->suspend_proc
&& !current_interpreter->procs->suspend_proc (current_interpreter->
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index c968a8f..8dfd3ee 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -168,9 +168,11 @@ mi_interpreter_prompt_p (void *data)
}
static void
-mi_interpreter_exec_continuation (struct continuation_arg *arg)
+mi_interpreter_exec_continuation (struct continuation_arg *arg, int error_p)
{
bpstat_do_actions (&stop_bpstat);
+ /* It's not clear what to do in the case of errror -- should we assume that
+ the target is stopped, or that it still runs? */
if (!target_executing)
{
fputs_unfiltered ("*stopped", raw_stdout);
@@ -178,7 +180,6 @@ mi_interpreter_exec_continuation (struct continuation_arg *arg)
fputs_unfiltered ("\n", raw_stdout);
fputs_unfiltered ("(gdb) \n", raw_stdout);
gdb_flush (raw_stdout);
- do_exec_cleanups (ALL_CLEANUPS);
}
else if (target_can_async_p ())
{
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 153d2b5..76e12f3 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -104,7 +104,8 @@ static void mi_execute_cli_command (const char *cmd, int args_p,
const char *args);
static enum mi_cmd_result mi_execute_async_cli_command (char *mi, char *args, int from_tty);
-static void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg);
+static void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg,
+ int error_p);
static int register_changed_p (int regnum, struct regcache *,
struct regcache *);
@@ -684,7 +685,6 @@ mi_cmd_target_select (char *args, int from_tty)
mi_out_put (uiout, raw_stdout);
mi_out_rewind (uiout);
fputs_unfiltered ("\n", raw_stdout);
- do_exec_cleanups (ALL_CLEANUPS);
return MI_CMD_QUIET;
}
@@ -1184,6 +1184,8 @@ mi_execute_command (char *cmd, int from_tty)
static enum mi_cmd_result
mi_cmd_execute (struct mi_parse *parse)
{
+ struct cleanup *cleanup;
+ enum mi_cmd_result r;
free_all_values ();
if (parse->cmd->argv_func != NULL
@@ -1222,11 +1224,19 @@ mi_cmd_execute (struct mi_parse *parse)
}
}
last_async_command = xstrdup (parse->token);
- make_exec_cleanup (free_current_contents, &last_async_command);
+ cleanup = make_cleanup (free_current_contents, &last_async_command);
/* FIXME: DELETE THIS! */
if (parse->cmd->args_func != NULL)
- return parse->cmd->args_func (parse->args, 0 /*from_tty */ );
- return parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
+ r = parse->cmd->args_func (parse->args, 0 /*from_tty */ );
+ else
+ r = parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
+ if (target_can_async_p () && target_executing)
+ /* last_async_command will be freed by continuation that
+ all execution command set. */
+ discard_cleanups (cleanup);
+ else
+ do_cleanups (cleanup);
+ return r;
}
else if (parse->cmd->cli.cmd != 0)
{
@@ -1287,24 +1297,12 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
{
struct cleanup *old_cleanups;
char *run;
- char *async_args;
if (target_can_async_p ())
- {
- async_args = (char *) xmalloc (strlen (args) + 2);
- make_exec_cleanup (free, async_args);
- strcpy (async_args, args);
- strcat (async_args, "&");
- run = xstrprintf ("%s %s", mi, async_args);
- make_exec_cleanup (free, run);
- add_continuation (mi_exec_async_cli_cmd_continuation, NULL);
- old_cleanups = NULL;
- }
+ run = xstrprintf ("%s %s&", mi, args);
else
- {
- run = xstrprintf ("%s %s", mi, args);
- old_cleanups = make_cleanup (xfree, run);
- }
+ run = xstrprintf ("%s %s", mi, args);
+ old_cleanups = make_cleanup (xfree, run);
if (!target_can_async_p ())
{
@@ -1326,11 +1324,24 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
if (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("^running\n", raw_stdout);
+
+ /* Ideally, we should be intalling continuation only when
+ the target is already running. However, this will break right now,
+ because continuation installed by the 'finish' command must be after
+ the continuation that prints *stopped. This issue will be
+ fixed soon. */
+ add_continuation (mi_exec_async_cli_cmd_continuation, NULL);
}
execute_command ( /*ui */ run, 0 /*from_tty */ );
- if (!target_can_async_p ())
+ if (target_can_async_p ())
+ {
+ /* If we're not executing, an exception should have been throw. */
+ gdb_assert (target_executing);
+ do_cleanups (old_cleanups);
+ }
+ else
{
/* Do this before doing any printing. It would appear that some
print code leaves garbage around in the buffer. */
@@ -1346,13 +1357,14 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
print_diff_now (current_command_ts);
fputs_unfiltered ("\n", raw_stdout);
return MI_CMD_QUIET;
- }
+ }
return MI_CMD_DONE;
}
void
-mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg)
+mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg, int error_p)
{
+ /* Assume 'error' means that target is stopped, too. */
if (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("*stopped", raw_stdout);
@@ -1360,7 +1372,11 @@ mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg)
fputs_unfiltered ("\n", raw_stdout);
fputs_unfiltered ("(gdb) \n", raw_stdout);
gdb_flush (raw_stdout);
- do_exec_cleanups (ALL_CLEANUPS);
+ if (last_async_command)
+ {
+ free (last_async_command);
+ last_async_command = NULL;
+ }
}
void
diff --git a/gdb/top.c b/gdb/top.c
index d9b5ce4..2454d24 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -368,7 +368,7 @@ do_chdir_cleanup (void *old_dir)
are always running synchronously. Or if we have just executed a
command that doesn't start the target. */
static void
-command_line_handler_continuation (struct continuation_arg *arg)
+command_line_handler_continuation (struct continuation_arg *arg, int error)
{
extern int display_time;
extern int display_space;
@@ -376,6 +376,9 @@ command_line_handler_continuation (struct continuation_arg *arg)
long time_at_cmd_start = arg->data.longint;
long space_at_cmd_start = arg->next->data.longint;
+ if (error)
+ return;
+
bpstat_do_actions (&stop_bpstat);
if (display_time)
diff --git a/gdb/utils.c b/gdb/utils.c
index 594fc73..d9953a0 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -104,7 +104,6 @@ static int debug_timestamp = 0;
static struct cleanup *cleanup_chain; /* cleaned up after a failed command */
static struct cleanup *final_cleanup_chain; /* cleaned up when gdb exits */
-static struct cleanup *exec_cleanup_chain; /* cleaned up on each execution command */
/* Pointer to what is left to do for an execution command after the
target stops. Used only in asynchronous mode, by targets that
@@ -214,12 +213,6 @@ make_final_cleanup (make_cleanup_ftype *function, void *arg)
return make_my_cleanup (&final_cleanup_chain, function, arg);
}
-struct cleanup *
-make_exec_cleanup (make_cleanup_ftype *function, void *arg)
-{
- return make_my_cleanup (&exec_cleanup_chain, function, arg);
-}
-
static void
do_freeargv (void *arg)
{
@@ -316,12 +309,6 @@ do_final_cleanups (struct cleanup *old_chain)
do_my_cleanups (&final_cleanup_chain, old_chain);
}
-void
-do_exec_cleanups (struct cleanup *old_chain)
-{
- do_my_cleanups (&exec_cleanup_chain, old_chain);
-}
-
static void
do_my_cleanups (struct cleanup **pmy_chain,
struct cleanup *old_chain)
@@ -440,7 +427,7 @@ null_cleanup (void *arg)
/* Add a continuation to the continuation list, the global list
cmd_continuation. The new continuation will be added at the front.*/
void
-add_continuation (void (*continuation_hook) (struct continuation_arg *),
+add_continuation (void (*continuation_hook) (struct continuation_arg *, int),
struct continuation_arg *arg_list)
{
struct continuation *continuation_ptr;
@@ -462,7 +449,7 @@ add_continuation (void (*continuation_hook) (struct continuation_arg *),
and do the continuations from there on, instead of using the
global beginning of list as our iteration pointer. */
void
-do_all_continuations (void)
+do_all_continuations (int error)
{
struct continuation *continuation_ptr;
struct continuation *saved_continuation;
@@ -477,7 +464,7 @@ do_all_continuations (void)
/* Work now on the list we have set aside. */
while (continuation_ptr)
{
- (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
+ (continuation_ptr->continuation_hook) (continuation_ptr->arg_list, error);
saved_continuation = continuation_ptr;
continuation_ptr = continuation_ptr->next;
xfree (saved_continuation);
@@ -504,7 +491,7 @@ discard_all_continuations (void)
the front. */
void
add_intermediate_continuation (void (*continuation_hook)
- (struct continuation_arg *),
+ (struct continuation_arg *, int),
struct continuation_arg *arg_list)
{
struct continuation *continuation_ptr;
@@ -526,7 +513,7 @@ add_intermediate_continuation (void (*continuation_hook)
and do the continuations from there on, instead of using the
global beginning of list as our iteration pointer.*/
void
-do_all_intermediate_continuations (void)
+do_all_intermediate_continuations (int error)
{
struct continuation *continuation_ptr;
struct continuation *saved_continuation;
@@ -541,7 +528,7 @@ do_all_intermediate_continuations (void)
/* Work now on the list we have set aside. */
while (continuation_ptr)
{
- (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
+ (continuation_ptr->continuation_hook) (continuation_ptr->arg_list, error);
saved_continuation = continuation_ptr;
continuation_ptr = continuation_ptr->next;
xfree (saved_continuation);