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.
This commit is contained in:
Vladimir Prus 2008-04-24 11:13:44 +00:00
parent 74960c6002
commit f107f56344
13 changed files with 219 additions and 204 deletions

View file

@ -1,3 +1,56 @@
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.

View file

@ -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)
{

View file

@ -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);

View file

@ -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). */

View file

@ -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

View file

@ -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:

View file

@ -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;

View file

@ -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);

View file

@ -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->

View file

@ -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 ())
{

View file

@ -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

View file

@ -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)

View file

@ -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);