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 Pedro Alves <pedro@codesourcery.com>
+
+ * 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 <bauerman@br.ibm.com>
Fix size of FPSCR in Power 7 processors.
/* 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\
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);
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."));
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)
{
#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. */
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);
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."));
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;
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)
{
}
else
{
+ ensure_valid_thread ();
ensure_not_running ();
clear_proceed_status ();
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
int thread = -1;
ERROR_NO_INFERIOR;
+ ensure_valid_thread ();
ensure_not_running ();
if (count_string)
int async_exec = 0;
ERROR_NO_INFERIOR;
+ ensure_valid_thread ();
ensure_not_running ();
/* Find out whether we must run in the background. */
dont_repeat (); /* Too dangerous. */
ERROR_NO_INFERIOR;
+ ensure_valid_thread ();
ensure_not_running ();
/* Find out whether we must run in the background. */
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
/* 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. */
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
&& 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\"",
}
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. */
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)
{
/* 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))
{
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);
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);
ui_out_message (uiout, 0, "\n\
The current thread <Thread ID %d> 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");
}
}
/* 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;
{
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
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);
{
if (!tidstr)
{
+ if (ptid_equal (inferior_ptid, null_ptid))
+ error (_("No thread selected"));
+
if (target_has_stack)
{
if (is_exited (inferior_ptid))
_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);
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;
/* 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