mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-05 23:26:51 +08:00
PR gdb/9747:
* gdbthread.h (finish_thread_state, finish_thread_state_cleanup): Declare. * thread.c (finish_thread_state, finish_thread_state_cleanup): New. * infrun.c (wait_for_inferior, fetch_inferior_event): If an error is thrown while handling an event, finish the thread state. (normal_stop): Use finish_thread_state cleanup. * infcmd.c (run_command_1): If an error is thrown while starting the inferior, finish the thread state.
This commit is contained in:
@ -1,3 +1,15 @@
|
|||||||
|
2009-01-18 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
|
PR gdb/9747:
|
||||||
|
* gdbthread.h (finish_thread_state, finish_thread_state_cleanup):
|
||||||
|
Declare.
|
||||||
|
* thread.c (finish_thread_state, finish_thread_state_cleanup): New.
|
||||||
|
* infrun.c (wait_for_inferior, fetch_inferior_event): If an error
|
||||||
|
is thrown while handling an event, finish the thread state.
|
||||||
|
(normal_stop): Use finish_thread_state cleanup.
|
||||||
|
* infcmd.c (run_command_1): If an error is thrown while starting
|
||||||
|
the inferior, finish the thread state.
|
||||||
|
|
||||||
2009-01-18 Pedro Alves <pedro@codesourcery.com>
|
2009-01-18 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
* tui/tui-winsource.c (tui_update_breakpoint_info): In asm layout,
|
* tui/tui-winsource.c (tui_update_breakpoint_info): In asm layout,
|
||||||
|
@ -288,6 +288,23 @@ extern void set_executing (ptid_t ptid, int executing);
|
|||||||
/* Reports if thread PTID is executing. */
|
/* Reports if thread PTID is executing. */
|
||||||
extern int is_executing (ptid_t ptid);
|
extern int is_executing (ptid_t ptid);
|
||||||
|
|
||||||
|
/* Merge the executing property of thread PTID over to its thread
|
||||||
|
state property (frontend running/stopped view).
|
||||||
|
|
||||||
|
"not executing" -> "stopped"
|
||||||
|
"executing" -> "running"
|
||||||
|
"exited" -> "exited"
|
||||||
|
|
||||||
|
If PIDGET (PTID) is -1, go over all threads.
|
||||||
|
|
||||||
|
Notifications are only emitted if the thread state did change. */
|
||||||
|
extern void finish_thread_state (ptid_t ptid);
|
||||||
|
|
||||||
|
/* Same as FINISH_THREAD_STATE, but with an interface suitable to be
|
||||||
|
registered as a cleanup. PTID_P points to the ptid_t that is
|
||||||
|
passed to FINISH_THREAD_STATE. */
|
||||||
|
extern void finish_thread_state_cleanup (void *ptid_p);
|
||||||
|
|
||||||
/* Commands with a prefix of `thread'. */
|
/* Commands with a prefix of `thread'. */
|
||||||
extern struct cmd_list_element *thread_cmd_list;
|
extern struct cmd_list_element *thread_cmd_list;
|
||||||
|
|
||||||
|
19
gdb/infcmd.c
19
gdb/infcmd.c
@ -456,6 +456,8 @@ static void
|
|||||||
run_command_1 (char *args, int from_tty, int tbreak_at_main)
|
run_command_1 (char *args, int from_tty, int tbreak_at_main)
|
||||||
{
|
{
|
||||||
char *exec_file;
|
char *exec_file;
|
||||||
|
struct cleanup *old_chain;
|
||||||
|
ptid_t ptid;
|
||||||
|
|
||||||
dont_repeat ();
|
dont_repeat ();
|
||||||
|
|
||||||
@ -544,14 +546,29 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
|
|||||||
target_create_inferior (exec_file, get_inferior_args (),
|
target_create_inferior (exec_file, get_inferior_args (),
|
||||||
environ_vector (inferior_environ), from_tty);
|
environ_vector (inferior_environ), from_tty);
|
||||||
|
|
||||||
|
/* We're starting off a new process. When we get out of here, in
|
||||||
|
non-stop mode, finish the state of all threads of that process,
|
||||||
|
but leave other threads alone, as they may be stopped in internal
|
||||||
|
events --- the frontend shouldn't see them as stopped. In
|
||||||
|
all-stop, always finish the state of all threads, as we may be
|
||||||
|
resuming more than just the new process. */
|
||||||
|
if (non_stop)
|
||||||
|
ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
|
||||||
|
else
|
||||||
|
ptid = minus_one_ptid;
|
||||||
|
old_chain = make_cleanup (finish_thread_state_cleanup, &ptid);
|
||||||
|
|
||||||
/* Pass zero for FROM_TTY, because at this point the "run" command
|
/* Pass zero for FROM_TTY, because at this point the "run" command
|
||||||
has done its thing; now we are setting up the running program. */
|
has done its thing; now we are setting up the running program. */
|
||||||
post_create_inferior (¤t_target, 0);
|
post_create_inferior (¤t_target, 0);
|
||||||
|
|
||||||
/* Start the target running. */
|
/* Start the target running. */
|
||||||
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
|
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Since there was no error, there's no need to finish the thread
|
||||||
|
states here. */
|
||||||
|
discard_cleanups (old_chain);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_command (char *args, int from_tty)
|
run_command (char *args, int from_tty)
|
||||||
|
51
gdb/infrun.c
51
gdb/infrun.c
@ -1783,6 +1783,8 @@ wait_for_inferior (int treat_exec_as_sigtrap)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
struct cleanup *old_chain;
|
||||||
|
|
||||||
if (deprecated_target_wait_hook)
|
if (deprecated_target_wait_hook)
|
||||||
ecs->ptid = deprecated_target_wait_hook (waiton_ptid, &ecs->ws);
|
ecs->ptid = deprecated_target_wait_hook (waiton_ptid, &ecs->ws);
|
||||||
else
|
else
|
||||||
@ -1795,9 +1797,17 @@ wait_for_inferior (int treat_exec_as_sigtrap)
|
|||||||
ecs->ws.value.sig = TARGET_SIGNAL_TRAP;
|
ecs->ws.value.sig = TARGET_SIGNAL_TRAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If an error happens while handling the event, propagate GDB's
|
||||||
|
knowledge of the executing state to the frontend/user running
|
||||||
|
state. */
|
||||||
|
old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
|
||||||
|
|
||||||
/* Now figure out what to do with the result of the result. */
|
/* Now figure out what to do with the result of the result. */
|
||||||
handle_inferior_event (ecs);
|
handle_inferior_event (ecs);
|
||||||
|
|
||||||
|
/* No error, don't finish the state yet. */
|
||||||
|
discard_cleanups (old_chain);
|
||||||
|
|
||||||
if (!ecs->wait_some_more)
|
if (!ecs->wait_some_more)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1820,6 +1830,7 @@ fetch_inferior_event (void *client_data)
|
|||||||
struct execution_control_state ecss;
|
struct execution_control_state ecss;
|
||||||
struct execution_control_state *ecs = &ecss;
|
struct execution_control_state *ecs = &ecss;
|
||||||
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
|
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
|
||||||
|
struct cleanup *ts_old_chain;
|
||||||
int was_sync = sync_execution;
|
int was_sync = sync_execution;
|
||||||
|
|
||||||
memset (ecs, 0, sizeof (*ecs));
|
memset (ecs, 0, sizeof (*ecs));
|
||||||
@ -1863,6 +1874,14 @@ fetch_inferior_event (void *client_data)
|
|||||||
thread. */
|
thread. */
|
||||||
context_switch (ecs->ptid);
|
context_switch (ecs->ptid);
|
||||||
|
|
||||||
|
/* If an error happens while handling the event, propagate GDB's
|
||||||
|
knowledge of the executing state to the frontend/user running
|
||||||
|
state. */
|
||||||
|
if (!non_stop)
|
||||||
|
ts_old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
|
||||||
|
else
|
||||||
|
ts_old_chain = make_cleanup (finish_thread_state_cleanup, &ecs->ptid);
|
||||||
|
|
||||||
/* Now figure out what to do with the result of the result. */
|
/* Now figure out what to do with the result of the result. */
|
||||||
handle_inferior_event (ecs);
|
handle_inferior_event (ecs);
|
||||||
|
|
||||||
@ -1886,6 +1905,9 @@ fetch_inferior_event (void *client_data)
|
|||||||
inferior_event_handler (INF_EXEC_COMPLETE, NULL);
|
inferior_event_handler (INF_EXEC_COMPLETE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No error, don't finish the thread states yet. */
|
||||||
|
discard_cleanups (ts_old_chain);
|
||||||
|
|
||||||
/* Revert thread and frame. */
|
/* Revert thread and frame. */
|
||||||
do_cleanups (old_chain);
|
do_cleanups (old_chain);
|
||||||
|
|
||||||
@ -4161,9 +4183,23 @@ normal_stop (void)
|
|||||||
{
|
{
|
||||||
struct target_waitstatus last;
|
struct target_waitstatus last;
|
||||||
ptid_t last_ptid;
|
ptid_t last_ptid;
|
||||||
|
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
|
||||||
|
|
||||||
get_last_target_status (&last_ptid, &last);
|
get_last_target_status (&last_ptid, &last);
|
||||||
|
|
||||||
|
/* If an exception is thrown from this point on, make sure to
|
||||||
|
propagate GDB's knowledge of the executing state to the
|
||||||
|
frontend/user running state. A QUIT is an easy exception to see
|
||||||
|
here, so do this before any filtered output. */
|
||||||
|
if (target_has_execution)
|
||||||
|
{
|
||||||
|
if (!non_stop)
|
||||||
|
old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
|
||||||
|
else if (last.kind != TARGET_WAITKIND_SIGNALLED
|
||||||
|
&& last.kind != TARGET_WAITKIND_EXITED)
|
||||||
|
old_chain = make_cleanup (finish_thread_state_cleanup, &inferior_ptid);
|
||||||
|
}
|
||||||
|
|
||||||
/* In non-stop mode, we don't want GDB to switch threads behind the
|
/* In non-stop mode, we don't want GDB to switch threads behind the
|
||||||
user's back, to avoid races where the user is typing a command to
|
user's back, to avoid races where the user is typing a command to
|
||||||
apply to thread x, but GDB switches to thread y before the user
|
apply to thread x, but GDB switches to thread y before the user
|
||||||
@ -4383,20 +4419,11 @@ done:
|
|||||||
/* Delete the breakpoint we stopped at, if it wants to be deleted.
|
/* Delete the breakpoint we stopped at, if it wants to be deleted.
|
||||||
Delete any breakpoint that is to be deleted at the next stop. */
|
Delete any breakpoint that is to be deleted at the next stop. */
|
||||||
breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
|
breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
|
||||||
|
|
||||||
/* Mark the stopped threads accordingly. In all-stop, all
|
|
||||||
threads of all processes are stopped when we get any event
|
|
||||||
reported. In non-stop mode, only the event thread stops. If
|
|
||||||
we're handling a process exit in non-stop mode, there's
|
|
||||||
nothing to do, as threads of the dead process are gone, and
|
|
||||||
threads of any other process were left running. */
|
|
||||||
if (!non_stop)
|
|
||||||
set_running (minus_one_ptid, 0);
|
|
||||||
else if (last.kind != TARGET_WAITKIND_SIGNALLED
|
|
||||||
&& last.kind != TARGET_WAITKIND_EXITED)
|
|
||||||
set_running (inferior_ptid, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tell the frontend about the new thread states. */
|
||||||
|
do_cleanups (old_chain);
|
||||||
|
|
||||||
/* Look up the hook_stop and run it (CLI internally handles problem
|
/* Look up the hook_stop and run it (CLI internally handles problem
|
||||||
of stop_command's pre-hook not existing). */
|
of stop_command's pre-hook not existing). */
|
||||||
if (stop_command)
|
if (stop_command)
|
||||||
|
49
gdb/thread.c
49
gdb/thread.c
@ -632,6 +632,55 @@ set_stop_requested (ptid_t ptid, int stop)
|
|||||||
observer_notify_thread_stop_requested (ptid);
|
observer_notify_thread_stop_requested (ptid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
finish_thread_state (ptid_t ptid)
|
||||||
|
{
|
||||||
|
struct thread_info *tp;
|
||||||
|
int all;
|
||||||
|
int any_started = 0;
|
||||||
|
|
||||||
|
all = ptid_equal (ptid, minus_one_ptid);
|
||||||
|
|
||||||
|
if (all || ptid_is_pid (ptid))
|
||||||
|
{
|
||||||
|
for (tp = thread_list; tp; tp = tp->next)
|
||||||
|
{
|
||||||
|
if (tp->state_ == THREAD_EXITED)
|
||||||
|
continue;
|
||||||
|
if (all || ptid_get_pid (ptid) == ptid_get_pid (tp->ptid))
|
||||||
|
{
|
||||||
|
if (tp->executing_ && tp->state_ == THREAD_STOPPED)
|
||||||
|
any_started = 1;
|
||||||
|
tp->state_ = tp->executing_ ? THREAD_RUNNING : THREAD_STOPPED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tp = find_thread_pid (ptid);
|
||||||
|
gdb_assert (tp);
|
||||||
|
if (tp->state_ != THREAD_EXITED)
|
||||||
|
{
|
||||||
|
if (tp->executing_ && tp->state_ == THREAD_STOPPED)
|
||||||
|
any_started = 1;
|
||||||
|
tp->state_ = tp->executing_ ? THREAD_RUNNING : THREAD_STOPPED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (any_started)
|
||||||
|
observer_notify_target_resumed (ptid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
finish_thread_state_cleanup (void *arg)
|
||||||
|
{
|
||||||
|
ptid_t *ptid_p = arg;
|
||||||
|
|
||||||
|
gdb_assert (arg);
|
||||||
|
|
||||||
|
finish_thread_state (*ptid_p);
|
||||||
|
}
|
||||||
|
|
||||||
/* Prints the list of threads and their details on UIOUT.
|
/* Prints the list of threads and their details on UIOUT.
|
||||||
This is a version of 'info_thread_command' suitable for
|
This is a version of 'info_thread_command' suitable for
|
||||||
use from MI.
|
use from MI.
|
||||||
|
Reference in New Issue
Block a user