* infrun.c (normal_stop): Use has_stack_frames instead of
authorPedro Alves <palves@redhat.com>
Wed, 25 Mar 2009 21:42:35 +0000 (21:42 +0000)
committerPedro Alves <palves@redhat.com>
Wed, 25 Mar 2009 21:42:35 +0000 (21:42 +0000)
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.

12 files changed:
gdb/ChangeLog
gdb/cli/cli-cmds.c
gdb/cli/cli-decode.c
gdb/cli/cli-decode.h
gdb/frame.c
gdb/infcmd.c
gdb/infrun.c
gdb/mi/mi-main.c
gdb/remote.c
gdb/stack.c
gdb/thread.c
gdb/top.c

index 9086bbefd348884c02071facaae0c3b5f268a54f..393f2690fbd760f944d2351d94eaa8f356ab1d5f 100644 (file)
@@ -1,3 +1,37 @@
+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.
index 1b40b4b3c199c879066b6d22e7c26d20fd2713b3..18d34bf6456d3d292b99b6e6553897717e724954 100644 (file)
@@ -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."));
 
index 8760ebf0d4ed7bc4acc34924a76bcd6312c3cd35..4ebf6dc619464523942125f283fe3149b3fdd3d4 100644 (file)
@@ -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)
 {
index 26ca2f75320be4d6aab141865097fc8ef33a2cf3..b6475e04d8f94f83c799ff65a1d9f82a2b53fee4 100644 (file)
@@ -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);
index 1d1856ec13f8324b79f5d32cafb2f20a90244034..b0a99fb5c7b7c2ff3eb6dd85c0413d2334e9f898 100644 (file)
@@ -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;
 
index fcabd3a42333f0d4d9884ad0e09c59d94d8cbabe..9cad3cb18652673fe47f047db94636ae954b21eb 100644 (file)
@@ -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
index 6600bbb2ba3bc2ac0bfcf2ec4c345a6ac5a4abef..4e270fc9f625d1c5e5199a6e70e6d991a8eba0a9 100644 (file)
@@ -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
index d7d8dc438ee269557fa950965682a8c02b72606e..f7a13805d80f1e43abec4438f4d61f51c17cc3f5 100644 (file)
@@ -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. */
index 950f71e3c0e5fd5f13c42512b690ae65991d9c49..e1e0db686cea1dff8e9ce654f2ff64301d918130 100644 (file)
@@ -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))
        {
index f185841ac20df3defbd8e732b5f8505056875e57..8146979cc484f51db20ff399b8440ad377cf5abe 100644 (file)
@@ -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);
index 52e442841ae4fc3bab01749b7fde34f247e1ccf9..fc3df6106b0f18bde268b93f34caf0e246f33295 100644 (file)
@@ -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 <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");
     }
 }
 
@@ -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);
index 0ee3df12b8191bfb743bbb369fefc585109c62d4..3aff25f98b9d653f2bf3f3bc60ac7408314bfb18 100644 (file)
--- 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