* defs.h (add_inferior_continuation)
(do_all_inferior_continuations) (discard_all_inferior_continuations): Declare. * utils.c (add_inferior_continuation) (do_all_inferior_continuations) (discard_all_inferior_continuations): New. * inferior.h (struct inferior) <continuations>: New field. * inferior.c (free_inferior): Discard all the inferior continuations. * inf-loop.c (inferior_event_handler): Do all current inferior continuations. * infcmd.c (attach_command): Register an inferior continuation instead of a thread continuation. * infrun.c (handle_inferior_event): If stop_soon is STOP_QUIETLY_NO_SIGSTOP, also expect a TARGET_SIGNAL_0.
This commit is contained in:
parent
6dc6b6558b
commit
e0ba674611
8 changed files with 107 additions and 5 deletions
|
@ -1,3 +1,21 @@
|
|||
2008-11-05 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* defs.h (add_inferior_continuation)
|
||||
(do_all_inferior_continuations)
|
||||
(discard_all_inferior_continuations): Declare.
|
||||
* utils.c (add_inferior_continuation)
|
||||
(do_all_inferior_continuations)
|
||||
(discard_all_inferior_continuations): New.
|
||||
* inferior.h (struct inferior) <continuations>: New field.
|
||||
* inferior.c (free_inferior): Discard all the inferior
|
||||
continuations.
|
||||
* inf-loop.c (inferior_event_handler): Do all current inferior
|
||||
continuations.
|
||||
* infcmd.c (attach_command): Register an inferior continuation
|
||||
instead of a thread continuation.
|
||||
* infrun.c (handle_inferior_event): If stop_soon is
|
||||
STOP_QUIETLY_NO_SIGSTOP, also expect a TARGET_SIGNAL_0.
|
||||
|
||||
2008-11-04 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* inf-loop.c (inferior_event_handler): On INF_ERROR and
|
||||
|
|
12
gdb/defs.h
12
gdb/defs.h
|
@ -701,8 +701,12 @@ extern void free_command_lines (struct command_line **);
|
|||
|
||||
struct continuation;
|
||||
struct thread_info;
|
||||
struct inferior;
|
||||
|
||||
/* From utils.c */
|
||||
|
||||
/* Thread specific continuations. */
|
||||
|
||||
extern void add_continuation (struct thread_info *,
|
||||
void (*)(void *), void *,
|
||||
void (*)(void *));
|
||||
|
@ -719,6 +723,14 @@ extern void do_all_intermediate_continuations_thread (struct thread_info *);
|
|||
extern void discard_all_intermediate_continuations (void);
|
||||
extern void discard_all_intermediate_continuations_thread (struct thread_info *);
|
||||
|
||||
/* Inferior specific (any thread) continuations. */
|
||||
|
||||
extern void add_inferior_continuation (void (*) (void *),
|
||||
void *,
|
||||
void (*) (void *));
|
||||
extern void do_all_inferior_continuations (void);
|
||||
extern void discard_all_inferior_continuations (struct inferior *inf);
|
||||
|
||||
/* String containing the current directory (what getwd would return). */
|
||||
|
||||
extern char *current_directory;
|
||||
|
|
|
@ -89,6 +89,11 @@ inferior_event_handler (enum inferior_event_type event_type,
|
|||
was_sync = sync_execution;
|
||||
async_enable_stdin ();
|
||||
|
||||
/* Do all continuations associated with the whole inferior (not
|
||||
a particular thread). */
|
||||
if (!ptid_equal (inferior_ptid, null_ptid))
|
||||
do_all_inferior_continuations ();
|
||||
|
||||
/* If we were doing a multi-step (eg: step n, next n), but it
|
||||
got interrupted by a breakpoint, still do the pending
|
||||
continuations. The continuation itself is responsible for
|
||||
|
|
|
@ -2320,9 +2320,8 @@ attach_command (char *args, int from_tty)
|
|||
a->args = xstrdup (args);
|
||||
a->from_tty = from_tty;
|
||||
a->async_exec = async_exec;
|
||||
add_continuation (inferior_thread (),
|
||||
attach_command_continuation, a,
|
||||
attach_command_continuation_free_args);
|
||||
add_inferior_continuation (attach_command_continuation, a,
|
||||
attach_command_continuation_free_args);
|
||||
discard_cleanups (back_to);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ current_inferior (void)
|
|||
static void
|
||||
free_inferior (struct inferior *inf)
|
||||
{
|
||||
discard_all_inferior_continuations (inf);
|
||||
xfree (inf->private);
|
||||
xfree (inf);
|
||||
}
|
||||
|
|
|
@ -424,6 +424,11 @@ struct inferior
|
|||
forked. */
|
||||
int attach_flag;
|
||||
|
||||
/* What is left to do for an execution command after any thread of
|
||||
this inferior stops. For continuations associated with a
|
||||
specific thread, see `struct thread_info'. */
|
||||
struct continuation *continuations;
|
||||
|
||||
/* Private data used by the target vector implementation. */
|
||||
struct private_inferior *private;
|
||||
};
|
||||
|
|
13
gdb/infrun.c
13
gdb/infrun.c
|
@ -2834,10 +2834,19 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
SIGTRAP. Some systems (e.g. Windows), and stubs supporting
|
||||
target extended-remote report it instead of a SIGSTOP
|
||||
(e.g. gdbserver). We already rely on SIGTRAP being our
|
||||
signal, so this is no exception. */
|
||||
signal, so this is no exception.
|
||||
|
||||
Also consider that the attach is complete when we see a
|
||||
TARGET_SIGNAL_0. In non-stop mode, GDB will explicitly tell
|
||||
the target to stop all threads of the inferior, in case the
|
||||
low level attach operation doesn't stop them implicitly. If
|
||||
they weren't stopped implicitly, then the stub will report a
|
||||
TARGET_SIGNAL_0, meaning: stopped for no particular reason
|
||||
other than GDB's request. */
|
||||
if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
|
||||
&& (ecs->event_thread->stop_signal == TARGET_SIGNAL_STOP
|
||||
|| ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP))
|
||||
|| ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
|
||||
|| ecs->event_thread->stop_signal == TARGET_SIGNAL_0))
|
||||
{
|
||||
stop_stepping (ecs);
|
||||
ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
|
||||
|
|
53
gdb/utils.c
53
gdb/utils.c
|
@ -505,6 +505,59 @@ add_continuation (struct thread_info *thread,
|
|||
thread->continuations = (struct continuation *) as_cleanup;
|
||||
}
|
||||
|
||||
/* Add a continuation to the continuation list of INFERIOR. The new
|
||||
continuation will be added at the front. */
|
||||
|
||||
void
|
||||
add_inferior_continuation (void (*continuation_hook) (void *), void *args,
|
||||
void (*continuation_free_args) (void *))
|
||||
{
|
||||
struct inferior *inf = current_inferior ();
|
||||
struct cleanup *as_cleanup = &inf->continuations->base;
|
||||
make_cleanup_ftype *continuation_hook_fn = continuation_hook;
|
||||
|
||||
make_my_cleanup2 (&as_cleanup,
|
||||
continuation_hook_fn,
|
||||
args,
|
||||
continuation_free_args);
|
||||
|
||||
inf->continuations = (struct continuation *) as_cleanup;
|
||||
}
|
||||
|
||||
/* Do all continuations of the current inferior. */
|
||||
|
||||
void
|
||||
do_all_inferior_continuations (void)
|
||||
{
|
||||
struct cleanup *old_chain;
|
||||
struct cleanup *as_cleanup;
|
||||
struct inferior *inf = current_inferior ();
|
||||
|
||||
if (inf->continuations == NULL)
|
||||
return;
|
||||
|
||||
/* Copy the list header into another pointer, and set the global
|
||||
list header to null, so that the global list can change as a side
|
||||
effect of invoking the continuations and the processing of the
|
||||
preexisting continuations will not be affected. */
|
||||
|
||||
as_cleanup = &inf->continuations->base;
|
||||
inf->continuations = NULL;
|
||||
|
||||
/* Work now on the list we have set aside. */
|
||||
do_my_cleanups (&as_cleanup, NULL);
|
||||
}
|
||||
|
||||
/* Get rid of all the inferior-wide continuations of INF. */
|
||||
|
||||
void
|
||||
discard_all_inferior_continuations (struct inferior *inf)
|
||||
{
|
||||
struct cleanup *continuation_ptr = &inf->continuations->base;
|
||||
discard_my_cleanups (&continuation_ptr, NULL);
|
||||
inf->continuations = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
restore_thread_cleanup (void *arg)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue