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:
parent
74960c6002
commit
f107f56344
13 changed files with 219 additions and 204 deletions
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
13
gdb/defs.h
13
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). */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
145
gdb/infcmd.c
145
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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->
|
||||
|
|
|
@ -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 ())
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
25
gdb/utils.c
25
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);
|
||||
|
|
Loading…
Reference in a new issue