diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 9086bbefd3..393f2690fb 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,37 @@ +2009-03-25 Pedro Alves + + * infrun.c (normal_stop): Use has_stack_frames instead of + target_has_stack. + * mi/mi-main.c (mi_execute_command): Avoid calling inferior_thread + when there is no thread selected. + (mi_cmd_execute): Don't special case commands that can run without + a valid selected thread. + * top.c (execute_command): Don't special case commands that can + run without a valid selected thread. Use has_stack_frames. + * infcmd.c (ensure_valid_thread): New. + (continue_1, step_1, jump_command, signal_command): Use it. + (detach_command): Error out if there's no selected thread/inferior. + * thread.c (print_thread_info): Allow having no thread selected. + (switch_to_thread): Don't read the PC if there is no current thread. + (do_restore_current_thread_cleanup): Don't record the current + frame if there is no current thread. + (make_cleanup_restore_current_thread): Don't read frame info if + there is no selected thread. + (_initialize_thread): Don't mark commands as + "no_selected_thread_ok". + * frame.c (get_current_frame): Error out if there is no valid + selected thread. + (has_stack_frames): Return false if there is no valid + selected thread. + * cli/cli-cmds.c (init_cli_cmds): Don't mark commands as + "no_selected_thread_ok". + * cli/cli-decode.c (set_cmd_no_selected_thread_ok) + (get_cmd_no_selected_thread_ok): Delete. + * cli/cli-decode.h (CMD_NO_SELECTED_THREAD_OK): Delete. + (set_cmd_no_selected_thread_ok, get_cmd_no_selected_thread_ok): + Delete declaration. + * stack.c (get_selected_block): Use has_stack_frames. + 2009-03-25 Thiago Jung Bauermann Fix size of FPSCR in Power 7 processors. diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index 1b40b4b3c1..18d34bf645 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -1248,9 +1248,8 @@ The commands below can be used to select other frames by number or address."), /* Define general commands. */ - c = add_com ("pwd", class_files, pwd_command, _("\ + add_com ("pwd", class_files, pwd_command, _("\ Print working directory. This is used for your program as well.")); - set_cmd_no_selected_thread_ok (c); c = add_cmd ("cd", class_files, cd_command, _("\ Set working directory to DIR for debugger and program being debugged.\n\ @@ -1291,7 +1290,6 @@ when GDB is started."), gdbinit); c = add_com ("help", class_support, help_command, _("Print list of commands.")); set_cmd_completer (c, command_completer); - set_cmd_no_selected_thread_ok (c); add_com_alias ("q", "quit", class_support, 1); add_com_alias ("h", "help", class_support, 1); @@ -1317,19 +1315,17 @@ Without an argument, history expansion is enabled."), show_history_expansion_p, &sethistlist, &showhistlist); - c = add_prefix_cmd ("info", class_info, info_command, _("\ + add_prefix_cmd ("info", class_info, info_command, _("\ Generic command for showing things about the program being debugged."), - &infolist, "info ", 0, &cmdlist); - set_cmd_no_selected_thread_ok (c); + &infolist, "info ", 0, &cmdlist); add_com_alias ("i", "info", class_info, 1); add_com ("complete", class_obscure, complete_command, _("List the completions for the rest of the line as a command.")); - c = add_prefix_cmd ("show", class_info, show_command, _("\ + add_prefix_cmd ("show", class_info, show_command, _("\ Generic command for showing things about the debugger."), - &showlist, "show ", 0, &cmdlist); - set_cmd_no_selected_thread_ok (c); + &showlist, "show ", 0, &cmdlist); /* Another way to get at the same thing. */ add_info ("set", show_command, _("Show all GDB settings.")); diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c index 8760ebf0d4..4ebf6dc619 100644 --- a/gdb/cli/cli-decode.c +++ b/gdb/cli/cli-decode.c @@ -112,18 +112,6 @@ get_cmd_context (struct cmd_list_element *cmd) return cmd->context; } -void -set_cmd_no_selected_thread_ok (struct cmd_list_element *cmd) -{ - cmd->flags |= CMD_NO_SELECTED_THREAD_OK; -} - -int -get_cmd_no_selected_thread_ok (struct cmd_list_element *cmd) -{ - return cmd->flags & CMD_NO_SELECTED_THREAD_OK; -} - enum cmd_types cmd_type (struct cmd_list_element *cmd) { diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h index 26ca2f7532..b6475e04d8 100644 --- a/gdb/cli/cli-decode.h +++ b/gdb/cli/cli-decode.h @@ -48,10 +48,6 @@ cmd_types; #define DEPRECATED_WARN_USER 0x2 #define MALLOCED_REPLACEMENT 0x4 -/* This flag is set if the command is allowed to run when the target - has execution, but there's no selected thread. */ -#define CMD_NO_SELECTED_THREAD_OK 0x10 - struct cmd_list_element { /* Points to next command in this list. */ @@ -259,13 +255,6 @@ extern int cmd_cfunc_eq (struct cmd_list_element *cmd, extern void set_cmd_context (struct cmd_list_element *cmd, void *context); extern void *get_cmd_context (struct cmd_list_element *cmd); -/* Mark command as ok to call when there is no selected thread. There - is no way to disable this once set. */ -extern void set_cmd_no_selected_thread_ok (struct cmd_list_element *); - -/* Return true if command is no-selected-thread-ok. */ -extern int get_cmd_no_selected_thread_ok (struct cmd_list_element *); - extern struct cmd_list_element *lookup_cmd (char **, struct cmd_list_element *, char *, int, int); diff --git a/gdb/frame.c b/gdb/frame.c index 1d1856ec13..b0a99fb5c7 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -980,6 +980,10 @@ get_current_frame (void) error (_("No stack.")); if (!target_has_memory) error (_("No memory.")); + if (ptid_equal (inferior_ptid, null_ptid)) + error (_("No selected thread.")); + if (is_exited (inferior_ptid)) + error (_("Invalid selected thread.")); if (is_executing (inferior_ptid)) error (_("Target is executing.")); @@ -1009,8 +1013,15 @@ has_stack_frames (void) if (!target_has_registers || !target_has_stack || !target_has_memory) return 0; - /* If the current thread is executing, don't try to read from - it. */ + /* No current inferior, no frame. */ + if (ptid_equal (inferior_ptid, null_ptid)) + return 0; + + /* Don't try to read from a dead thread. */ + if (is_exited (inferior_ptid)) + return 0; + + /* ... or from a spinning thread. */ if (is_executing (inferior_ptid)) return 0; diff --git a/gdb/infcmd.c b/gdb/infcmd.c index fcabd3a423..9cad3cb186 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -616,6 +616,15 @@ proceed_thread_callback (struct thread_info *thread, void *arg) return 0; } +void +ensure_valid_thread (void) +{ + if (ptid_equal (inferior_ptid, null_ptid) + || is_exited (inferior_ptid)) + error (_("\ +Cannot execute this command without a live selected thread.")); +} + void continue_1 (int all_threads) { @@ -637,6 +646,7 @@ continue_1 (int all_threads) } else { + ensure_valid_thread (); ensure_not_running (); clear_proceed_status (); proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); @@ -781,6 +791,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) int thread = -1; ERROR_NO_INFERIOR; + ensure_valid_thread (); ensure_not_running (); if (count_string) @@ -991,6 +1002,7 @@ jump_command (char *arg, int from_tty) int async_exec = 0; ERROR_NO_INFERIOR; + ensure_valid_thread (); ensure_not_running (); /* Find out whether we must run in the background. */ @@ -1092,6 +1104,7 @@ signal_command (char *signum_exp, int from_tty) dont_repeat (); /* Too dangerous. */ ERROR_NO_INFERIOR; + ensure_valid_thread (); ensure_not_running (); /* Find out whether we must run in the background. */ @@ -2383,6 +2396,10 @@ void detach_command (char *args, int from_tty) { dont_repeat (); /* Not for the faint of heart. */ + + if (ptid_equal (inferior_ptid, null_ptid)) + error (_("The program is not being run.")); + target_detach (args, from_tty); /* If the solist is global across inferiors, don't clear it when we diff --git a/gdb/infrun.c b/gdb/infrun.c index 6600bbb2ba..4e270fc9f6 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -4302,7 +4302,7 @@ Further execution is probably impossible.\n")); /* Set the current source location. This will also happen if we display the frame below, but the current SAL will be incorrect during a user hook-stop function. */ - if (target_has_stack && !stop_stack_dummy) + if (has_stack_frames () && !stop_stack_dummy) set_current_sal_from_frame (get_current_frame (), 1); /* Let the user/frontend see the threads as stopped. */ @@ -4314,7 +4314,7 @@ Further execution is probably impossible.\n")); catch_errors (hook_stop_stub, stop_command, "Error while running hook_stop:\n", RETURN_MASK_ALL); - if (!target_has_stack) + if (!has_stack_frames ()) goto done; if (last.kind == TARGET_WAITKIND_SIGNALLED diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index d7d8dc438e..f7a13805d8 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -1284,21 +1284,23 @@ mi_execute_command (char *cmd, int from_tty) && strcmp (command->command, "thread-select") != 0) { struct mi_interp *mi = top_level_interpreter_data (); - struct thread_info *ti = inferior_thread (); - int report_change; + int report_change = 0; if (command->thread == -1) { - report_change = !ptid_equal (previous_ptid, null_ptid) - && !ptid_equal (inferior_ptid, previous_ptid); + report_change = (!ptid_equal (previous_ptid, null_ptid) + && !ptid_equal (inferior_ptid, previous_ptid) + && !ptid_equal (inferior_ptid, null_ptid)); } - else + else if (!ptid_equal (inferior_ptid, null_ptid)) { + struct thread_info *ti = inferior_thread (); report_change = (ti->num != command->thread); } if (report_change) { + struct thread_info *ti = inferior_thread (); target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "thread-selected,id=\"%d\"", @@ -1353,28 +1355,7 @@ mi_cmd_execute (struct mi_parse *parse) } if (parse->cmd->argv_func != NULL) - { - if (target_can_async_p () - && target_has_execution - && is_exited (inferior_ptid) - && (strcmp (parse->command, "thread-info") != 0 - && strcmp (parse->command, "thread-list-ids") != 0 - && strcmp (parse->command, "thread-select") != 0 - && strcmp (parse->command, "list-thread-groups") != 0)) - { - struct ui_file *stb; - stb = mem_fileopen (); - - fputs_unfiltered ("Cannot execute command ", stb); - fputstr_unfiltered (parse->command, '"', stb); - fputs_unfiltered (" without a selected thread", stb); - - make_cleanup_ui_file_delete (stb); - error_stream (stb); - } - - parse->cmd->argv_func (parse->command, parse->argv, parse->argc); - } + parse->cmd->argv_func (parse->command, parse->argv, parse->argc); else if (parse->cmd->cli.cmd != 0) { /* FIXME: DELETE THIS. */ diff --git a/gdb/remote.c b/gdb/remote.c index 950f71e3c0..e1e0db686c 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -6606,19 +6606,6 @@ remote_mourn_1 (struct target_ops *target) generic_mourn_inferior (); } -static int -select_new_thread_callback (struct thread_info *th, void* data) -{ - if (!is_exited (th->ptid)) - { - switch_to_thread (th->ptid); - printf_filtered (_("[Switching to %s]\n"), - target_pid_to_str (inferior_ptid)); - return 1; - } - return 0; -} - static void extended_remote_mourn_1 (struct target_ops *target) { @@ -6662,16 +6649,7 @@ extended_remote_mourn_1 (struct target_ops *target) /* Call common code to mark the inferior as not running. */ generic_mourn_inferior (); - if (have_inferiors ()) - { - extern void nullify_last_target_wait_ptid (); - /* Multi-process case. The current process has exited, but - there are other processes to debug. Switch to the first - available. */ - iterate_over_threads (select_new_thread_callback, NULL); - nullify_last_target_wait_ptid (); - } - else + if (!have_inferiors ()) { if (!remote_multi_process_p (rs)) { diff --git a/gdb/stack.c b/gdb/stack.c index f185841ac2..8146979cc4 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -1694,13 +1694,7 @@ select_and_print_frame (struct frame_info *frame) struct block * get_selected_block (CORE_ADDR *addr_in_block) { - if (!target_has_stack) - return 0; - - if (is_exited (inferior_ptid)) - return 0; - - if (is_executing (inferior_ptid)) + if (!has_stack_frames ()) return 0; return get_frame_block (get_selected_frame (NULL), addr_in_block); diff --git a/gdb/thread.c b/gdb/thread.c index 52e442841a..fc3df6106b 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -785,10 +785,11 @@ print_thread_info (struct ui_out *uiout, int requested_thread, int pid) the "info threads" command. */ do_cleanups (old_chain); - if (pid == -1 && requested_thread == -1 ) + if (pid == -1 && requested_thread == -1) { gdb_assert (current_thread != -1 - || !thread_list); + || !thread_list + || ptid_equal (inferior_ptid, null_ptid)); if (current_thread != -1 && ui_out_is_mi_like_p (uiout)) ui_out_field_int (uiout, "current-thread-id", current_thread); @@ -796,6 +797,11 @@ print_thread_info (struct ui_out *uiout, int requested_thread, int pid) ui_out_message (uiout, 0, "\n\ The current thread has terminated. See `help thread'.\n", current_thread); + else if (thread_list + && current_thread == -1 + && ptid_equal (current_ptid, null_ptid)) + ui_out_message (uiout, 0, "\n\ +No selected thread. See `help thread'.\n"); } } @@ -828,7 +834,9 @@ switch_to_thread (ptid_t ptid) /* We don't check for is_stopped, because we're called at times while in the TARGET_RUNNING state, e.g., while handling an internal event. */ - if (!is_exited (ptid) && !is_executing (ptid)) + if (!ptid_equal (inferior_ptid, null_ptid) + && !is_exited (ptid) + && !is_executing (ptid)) stop_pc = read_pc (); else stop_pc = ~(CORE_ADDR) 0; @@ -909,11 +917,24 @@ do_restore_current_thread_cleanup (void *arg) { struct thread_info *tp; struct current_thread_cleanup *old = arg; - restore_current_thread (old->inferior_ptid); + + tp = find_thread_pid (old->inferior_ptid); + + /* If the previously selected thread belonged to a process that has + in the mean time been deleted (due to normal exit, detach, etc.), + then don't revert back to it, but instead simply drop back to no + thread selected. */ + if (tp + && is_exited (tp->ptid) + && find_inferior_pid (ptid_get_pid (tp->ptid)) == NULL) + restore_current_thread (null_ptid); + else + restore_current_thread (old->inferior_ptid); /* The running state of the originally selected thread may have changed, so we have to recheck it here. */ - if (old->was_stopped + if (!ptid_equal (inferior_ptid, null_ptid) + && old->was_stopped && is_stopped (inferior_ptid) && target_has_registers && target_has_stack @@ -942,21 +963,25 @@ make_cleanup_restore_current_thread (void) old = xmalloc (sizeof (struct current_thread_cleanup)); old->inferior_ptid = inferior_ptid; - old->was_stopped = is_stopped (inferior_ptid); - if (old->was_stopped - && target_has_registers - && target_has_stack - && target_has_memory) - frame = get_selected_frame (NULL); - else - frame = NULL; - old->selected_frame_id = get_frame_id (frame); - old->selected_frame_level = frame_relative_level (frame); + if (!ptid_equal (inferior_ptid, null_ptid)) + { + old->was_stopped = is_stopped (inferior_ptid); + if (old->was_stopped + && target_has_registers + && target_has_stack + && target_has_memory) + frame = get_selected_frame (NULL); + else + frame = NULL; - tp = find_thread_pid (inferior_ptid); - if (tp) - tp->refcount++; + old->selected_frame_id = get_frame_id (frame); + old->selected_frame_level = frame_relative_level (frame); + + tp = find_thread_pid (inferior_ptid); + if (tp) + tp->refcount++; + } return make_cleanup_dtor (do_restore_current_thread_cleanup, old, restore_current_thread_cleanup_dtor); @@ -1086,6 +1111,9 @@ thread_command (char *tidstr, int from_tty) { if (!tidstr) { + if (ptid_equal (inferior_ptid, null_ptid)) + error (_("No thread selected")); + if (target_has_stack) { if (is_exited (inferior_ptid)) @@ -1172,26 +1200,21 @@ void _initialize_thread (void) { static struct cmd_list_element *thread_apply_list = NULL; - struct cmd_list_element *c; - c = add_info ("threads", info_threads_command, - _("IDs of currently known threads.")); - set_cmd_no_selected_thread_ok (c); + add_info ("threads", info_threads_command, + _("IDs of currently known threads.")); - c = add_prefix_cmd ("thread", class_run, thread_command, _("\ + add_prefix_cmd ("thread", class_run, thread_command, _("\ Use this command to switch between threads.\n\ The new thread ID must be currently known."), - &thread_cmd_list, "thread ", 1, &cmdlist); - set_cmd_no_selected_thread_ok (c); + &thread_cmd_list, "thread ", 1, &cmdlist); - c = add_prefix_cmd ("apply", class_run, thread_apply_command, - _("Apply a command to a list of threads."), - &thread_apply_list, "thread apply ", 1, &thread_cmd_list); - set_cmd_no_selected_thread_ok (c); + add_prefix_cmd ("apply", class_run, thread_apply_command, + _("Apply a command to a list of threads."), + &thread_apply_list, "thread apply ", 1, &thread_cmd_list); - c = add_cmd ("all", class_run, thread_apply_all_command, - _("Apply a command to all threads."), &thread_apply_list); - set_cmd_no_selected_thread_ok (c); + add_cmd ("all", class_run, thread_apply_all_command, + _("Apply a command to all threads."), &thread_apply_list); if (!xdb_commands) add_com_alias ("t", "thread", class_run, 1); diff --git a/gdb/top.c b/gdb/top.c index 0ee3df12b8..3aff25f98b 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -400,14 +400,6 @@ execute_command (char *p, int from_tty) c = lookup_cmd (&p, cmdlist, "", 0, 1); - /* If the selected thread has terminated, we allow only a - limited set of commands. */ - if (target_can_async_p () - && is_exited (inferior_ptid) - && !get_cmd_no_selected_thread_ok (c)) - error (_("\ -Cannot execute this command without a live selected thread. See `help thread'.")); - /* Pass null arg rather than an empty one. */ arg = *p ? p : 0; @@ -469,7 +461,7 @@ Cannot execute this command without a live selected thread. See `help thread'." /* FIXME: This should be cacheing the frame and only running when the frame changes. */ - if (target_has_stack && is_stopped (inferior_ptid)) + if (has_stack_frames ()) { flang = get_frame_language (); if (!warned