diff options
author | Pedro Alves <palves@redhat.com> | 2008-07-11 11:07:39 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2008-07-11 11:07:39 +0000 |
commit | 4f8d22e3b4e0e9a71f94f24deb77d2f4753deb85 (patch) | |
tree | 2c8b6857cf1322ed3a4f1d17b143dcec74ef164d /gdb/infrun.c | |
parent | 8cae4b3f0b7457fe342df1784b21e2a48086db83 (diff) | |
download | gdb-4f8d22e3b4e0e9a71f94f24deb77d2f4753deb85.zip gdb-4f8d22e3b4e0e9a71f94f24deb77d2f4753deb85.tar.gz gdb-4f8d22e3b4e0e9a71f94f24deb77d2f4753deb85.tar.bz2 |
Exited threads.
* thread.c (enum thread_state): New.
(thread_state main_thread_running): Delete, in favor of...
(thread_state main_thread_state): ... this. Update throughout.
(clear_thread_inferior_resources): New, split from free_thread.
(free_thread): Call clear_thread_inferior_resources.
(init_thread_list): Set main thread to stopped state.
(add_thread_silent): Take care of PTID reuses.
(delete_thread): If deleting inferior_ptid or a thread with
refcount > 0, mark it as exited, but still keep it in the list.
Only notify of thread exits, if we haven't done so yet.
(iterate_over_threads): Make it safe to delete threads while
iterating over them.
(do_captured_list_thread_ids): Don't account for exited threads.
(thread_alive): Check for the THREAD_EXITED state, and don't set
ptid to -1 on exited threads.
(set_running): Update to account for extra possible states.
(is_thread_state): New.
(is_stopped, is_exited): New.
(is_running): Implement in terms of is_thread_state.
(any_running): Update.
(print_thread_info): Update. Account for exited threads. Don't
warn about missed frame restoring here, its done in the cleanup.
(switch_to_thread): Don't read from a thread that has gone.
(restore_current_thread): In non-stop mode, do a full context
switch.
(restore_selected_frame): Add a frame_level argument. Rewrite.
(struct current_thread_cleanup): Add selected_frame_level and
was_stopped members.
(do_restore_current_thread_cleanup): Check if thread was stopped
and still is, and if the target has registers, stack and memory
before restoring the selected frame. Don't delete the cleanup
argument here.
(restore_current_thread_cleanup_dtor): New.
(make_cleanup_restore_current_thread): Remove all arguments.
Rewrite.
(thread_apply_all_command): Update. Prune threads.
(thread_apply_command): Update.
(thread_command): Account for currently selected exited thread.
(do_captured_thread_select): Check for a running thread. Prune
threads.
(_initialize_thread): Make "info threads", "thread", "thread
apply", and "thread apply all" appliable without a selected thread.
* gdbthread.h (struct thread_info): Replace running_ by state_.
Add refcount.
(is_exited, is_stopped): Declare.
(make_cleanup_restore_current_thread): Remove all arguments.
* infrun.c: Include "event-top.h".
(fetch_inferior_event): In non-stop mode, restore selected thread
and frame after handling the event and running breakpoint
commands. Display GDB prompt if needed.
(normal_stop): In non-stop mode, don't print thread switching
notice.
* cli/cli-decode.c (set_cmd_no_selected_thread_ok)
(get_cmd_no_selected_thread_ok): New.
* cli/cli-decode.h (CMD_NO_SELECTED_THREAD_OK): New.
(set_cmd_no_selected_thread_ok, get_cmd_no_selected_thread_ok):
Declare.
* cli/cli-cmds.c: Set "pwd", "help", "info", "show" as
no-selected-thread ok.
* top.c (execute_command): Check for non no-selected-thread-ok
commands.
* linux-nat.c (struct saved_ptids, threads_to_delete)
(record_dead_thread, prune_lwps): Delete.
(exit_lwp): Unconditionally delete thread.
(linux_nat_resume): Remove prune_lwps call.
* infcmd.c (proceed_thread_callback): Check if !is_stopped instead
of is_running. Adjust to make_cleanup_restore_current_thread
interface change.
* mi/mi-main.c (mi_cmd_execute): Only allow a few commands if the
selected thread has exited.
* inf-loop.c (inferior_event_handler): Don't display the prompt
here.
* varobj.c (c_value_of_root): Update.
* defs.h (make_cleanup_dtor): Declare.
* utils.c (make_cleanup_dtor): New.
* Makefile.in (infrun.o): Depend on $(event_top_h).
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index f74b945..44e6790 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -48,6 +48,7 @@ #include "gdb_assert.h" #include "mi/mi-common.h" +#include "event-top.h" /* Prototypes for local functions */ @@ -1530,11 +1531,20 @@ fetch_inferior_event (void *client_data) { struct execution_control_state ecss; struct execution_control_state *ecs = &ecss; + struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); + int was_sync = sync_execution; memset (ecs, 0, sizeof (*ecs)); overlay_cache_invalid = 1; + if (non_stop) + /* In non-stop mode, the user/frontend should not notice a thread + switch due to internal events. Make sure we reverse to the + user selected thread and frame after handling the event and + running any breakpoint commands. */ + make_cleanup_restore_current_thread (); + /* We have to invalidate the registers BEFORE calling target_wait because they can be loaded from the target while in target_wait. This makes remote debugging a bit more efficient for those @@ -1571,6 +1581,14 @@ fetch_inferior_event (void *client_data) else inferior_event_handler (INF_EXEC_COMPLETE, NULL); } + + /* Revert thread and frame. */ + do_cleanups (old_chain); + + /* If the inferior was in sync execution mode, and now isn't, + restore the prompt. */ + if (was_sync && !sync_execution) + display_gdb_prompt (0); } /* Prepare an execution control state for looping through a @@ -3709,6 +3727,11 @@ normal_stop (void) get_last_target_status (&last_ptid, &last); + /* 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 + apply to thread x, but GDB switches to thread y before the user + finishes entering the command. */ + /* As with the notification of thread events, we want to delay notifying the user that we've switched thread context until the inferior actually stops. @@ -3716,7 +3739,8 @@ normal_stop (void) There's no point in saying anything if the inferior has exited. Note that SIGNALLED here means "exited with a signal", not "received a signal". */ - if (!ptid_equal (previous_inferior_ptid, inferior_ptid) + if (!non_stop + && !ptid_equal (previous_inferior_ptid, inferior_ptid) && target_has_execution && last.kind != TARGET_WAITKIND_SIGNALLED && last.kind != TARGET_WAITKIND_EXITED) |