gdb: fix vfork with multiple threads
[deliverable/binutils-gdb.git] / gdb / inferior.c
index d732690a3cd66ca68af5ad2b30bee3b879c8ff12..e1c70d553fde27c9fe12c398c108d24e8ad9f5ca 100644 (file)
@@ -1,6 +1,6 @@
 /* Multi-process control for GDB, the GNU debugger.
 
-   Copyright (C) 2008-2020 Free Software Foundation, Inc.
+   Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -31,7 +31,6 @@
 #include "symfile.h"
 #include "gdbsupport/environ.h"
 #include "cli/cli-utils.h"
-#include "continuations.h"
 #include "arch-utils.h"
 #include "target-descriptions.h"
 #include "readline/tilde.h"
@@ -51,12 +50,12 @@ bool print_inferior_events = true;
 /* The Current Inferior.  This is a strong reference.  I.e., whenever
    an inferior is the current inferior, its refcount is
    incremented.  */
-static struct inferior *current_inferior_ = NULL;
+static inferior_ref current_inferior_;
 
 struct inferior*
 current_inferior (void)
 {
-  return current_inferior_;
+  return current_inferior_.get ();
 }
 
 void
@@ -65,9 +64,7 @@ set_current_inferior (struct inferior *inf)
   /* There's always an inferior.  */
   gdb_assert (inf != NULL);
 
-  inf->incref ();
-  current_inferior_->decref ();
-  current_inferior_ = inf;
+  current_inferior_ = inferior_ref::new_reference (inf);
 }
 
 private_inferior::~private_inferior () = default;
@@ -76,10 +73,8 @@ inferior::~inferior ()
 {
   inferior *inf = this;
 
-  discard_all_inferior_continuations (inf);
+  m_continuations.clear ();
   inferior_free_data (inf);
-  xfree (inf->args);
-  xfree (inf->terminal);
   target_desc_info_free (inf->tdesc_info);
 }
 
@@ -94,6 +89,38 @@ inferior::inferior (int pid_)
   m_target_stack.push (get_dummy_target ());
 }
 
+void
+inferior::set_tty (const char *terminal_name)
+{
+  if (terminal_name != nullptr && *terminal_name != '\0')
+    m_terminal = make_unique_xstrdup (terminal_name);
+  else
+    m_terminal = NULL;
+}
+
+const char *
+inferior::tty ()
+{
+  return m_terminal.get ();
+}
+
+void
+inferior::add_continuation (std::function<void ()> &&cont)
+{
+  m_continuations.emplace_front (std::move (cont));
+}
+
+void
+inferior::do_all_continuations ()
+{
+  while (!m_continuations.empty ())
+    {
+      auto iter = m_continuations.begin ();
+      (*iter) ();
+      m_continuations.erase (iter);
+    }
+}
+
 struct inferior *
 add_inferior_silent (int pid)
 {
@@ -161,8 +188,8 @@ delete_inferior (struct inferior *todel)
   gdb::observers::inferior_removed.notify (inf);
 
   /* If this program space is rendered useless, remove it. */
-  if (program_space_empty_p (inf->pspace))
-    delete_program_space (inf->pspace);
+  if (inf->pspace->empty ())
+    delete inf->pspace;
 
   delete inf;
 }
@@ -260,13 +287,6 @@ inferior_appeared (struct inferior *inf, int pid)
   gdb::observers::inferior_appeared.notify (inf);
 }
 
-void
-discard_all_inferiors (void)
-{
-  for (inferior *inf : all_non_exited_inferiors ())
-    exit_inferior_silent (inf);
-}
-
 struct inferior *
 find_inferior_id (int num)
 {
@@ -317,17 +337,6 @@ find_inferior_for_program_space (struct program_space *pspace)
   return NULL;
 }
 
-struct inferior *
-iterate_over_inferiors (int (*callback) (struct inferior *, void *),
-                       void *data)
-{
-  for (inferior *inf : all_inferiors_safe ())
-    if ((*callback) (inf, data))
-      return inf;
-
-  return NULL;
-}
-
 int
 have_inferiors (void)
 {
@@ -419,7 +428,7 @@ void
 print_selected_inferior (struct ui_out *uiout)
 {
   struct inferior *inf = current_inferior ();
-  const char *filename = inf->pspace->pspace_exec_filename;
+  const char *filename = inf->pspace->exec_filename.get ();
 
   if (filename == NULL)
     filename = _("<noexec>");
@@ -428,6 +437,31 @@ print_selected_inferior (struct ui_out *uiout)
                  inf->num, inferior_pid_to_str (inf->pid).c_str (), filename);
 }
 
+/* Helper for print_inferior.  Returns the 'connection-id' string for
+   PROC_TARGET.  */
+
+static std::string
+uiout_field_connection (process_stratum_target *proc_target)
+{
+  if (proc_target == NULL)
+    {
+      return {};
+    }
+  else if (proc_target->connection_string () != NULL)
+    {
+      return string_printf ("%d (%s %s)",
+                           proc_target->connection_number,
+                           proc_target->shortname (),
+                           proc_target->connection_string ());
+    }
+  else
+    {
+      return string_printf ("%d (%s)",
+                           proc_target->connection_number,
+                           proc_target->shortname ());
+    }
+}
+
 /* Prints the list of inferiors and their details on UIOUT.  This is a
    version of 'info_inferior_command' suitable for use from MI.
 
@@ -439,6 +473,7 @@ static void
 print_inferior (struct ui_out *uiout, const char *requested_inferiors)
 {
   int inf_count = 0;
+  size_t connection_id_len = 20;
 
   /* Compute number of inferiors we will print.  */
   for (inferior *inf : all_inferiors ())
@@ -446,6 +481,10 @@ print_inferior (struct ui_out *uiout, const char *requested_inferiors)
       if (!number_is_in_list (requested_inferiors, inf->num))
        continue;
 
+      std::string conn = uiout_field_connection (inf->process_target ());
+      if (connection_id_len < conn.size ())
+       connection_id_len = conn.size ();
+
       ++inf_count;
     }
 
@@ -455,13 +494,20 @@ print_inferior (struct ui_out *uiout, const char *requested_inferiors)
       return;
     }
 
-  ui_out_emit_table table_emitter (uiout, 4, inf_count, "inferiors");
+  ui_out_emit_table table_emitter (uiout, 5, inf_count, "inferiors");
   uiout->table_header (1, ui_left, "current", "");
   uiout->table_header (4, ui_left, "number", "Num");
   uiout->table_header (17, ui_left, "target-id", "Description");
+  uiout->table_header (connection_id_len, ui_left,
+                      "connection-id", "Connection");
   uiout->table_header (17, ui_left, "exec", "Executable");
 
   uiout->table_body ();
+
+  /* Restore the current thread after the loop because we switch the
+     inferior in the loop.  */
+  scoped_restore_current_pspace_and_thread restore_pspace_thread;
+  inferior *current_inf = current_inferior ();
   for (inferior *inf : all_inferiors ())
     {
       if (!number_is_in_list (requested_inferiors, inf->num))
@@ -469,17 +515,24 @@ print_inferior (struct ui_out *uiout, const char *requested_inferiors)
 
       ui_out_emit_tuple tuple_emitter (uiout, NULL);
 
-      if (inf == current_inferior ())
+      if (inf == current_inf)
        uiout->field_string ("current", "*");
       else
        uiout->field_skip ("current");
 
       uiout->field_signed ("number", inf->num);
 
+      /* Because target_pid_to_str uses the current inferior,
+        switch the inferior.  */
+      switch_to_inferior_no_thread (inf);
+
       uiout->field_string ("target-id", inferior_pid_to_str (inf->pid));
 
-      if (inf->pspace->pspace_exec_filename != NULL)
-       uiout->field_string ("exec", inf->pspace->pspace_exec_filename);
+      std::string conn = uiout_field_connection (inf->process_target ());
+      uiout->field_string ("connection-id", conn);
+
+      if (inf->pspace->exec_filename != nullptr)
+       uiout->field_string ("exec", inf->pspace->exec_filename.get ());
       else
        uiout->field_skip ("exec");
 
@@ -507,6 +560,8 @@ detach_inferior_command (const char *args, int from_tty)
   if (!args || !*args)
     error (_("Requires argument (inferior id(s) to detach)"));
 
+  scoped_restore_current_thread restore_thread;
+
   number_or_range_parser parser (args);
   while (!parser.finished ())
     {
@@ -544,6 +599,8 @@ kill_inferior_command (const char *args, int from_tty)
   if (!args || !*args)
     error (_("Requires argument (inferior id(s) to kill)"));
 
+  scoped_restore_current_thread restore_thread;
+
   number_or_range_parser parser (args);
   while (!parser.finished ())
     {
@@ -593,34 +650,50 @@ inferior_command (const char *args, int from_tty)
   struct inferior *inf;
   int num;
 
-  num = parse_and_eval_long (args);
-
-  inf = find_inferior_id (num);
-  if (inf == NULL)
-    error (_("Inferior ID %d not known."), num);
-
-  if (inf->pid != 0)
+  if (args == nullptr)
     {
-      if (inf != current_inferior ())
-       {
-         thread_info *tp = any_thread_of_inferior (inf);
-         if (tp == NULL)
-           error (_("Inferior has no threads."));
+      inf = current_inferior ();
+      gdb_assert (inf != nullptr);
+      const char *filename = inf->pspace->exec_filename.get ();
 
-         switch_to_thread (tp);
-       }
+      if (filename == nullptr)
+       filename = _("<noexec>");
 
-      gdb::observers::user_selected_context_changed.notify
-       (USER_SELECTED_INFERIOR
-        | USER_SELECTED_THREAD
-        | USER_SELECTED_FRAME);
+      printf_filtered (_("[Current inferior is %d [%s] (%s)]\n"),
+                      inf->num, inferior_pid_to_str (inf->pid).c_str (),
+                      filename);
     }
   else
     {
-      switch_to_inferior_no_thread (inf);
+      num = parse_and_eval_long (args);
 
-      gdb::observers::user_selected_context_changed.notify
-       (USER_SELECTED_INFERIOR);
+      inf = find_inferior_id (num);
+      if (inf == NULL)
+       error (_("Inferior ID %d not known."), num);
+
+      if (inf->pid != 0)
+       {
+         if (inf != current_inferior ())
+           {
+             thread_info *tp = any_thread_of_inferior (inf);
+             if (tp == NULL)
+               error (_("Inferior has no threads."));
+
+             switch_to_thread (tp);
+           }
+
+         gdb::observers::user_selected_context_changed.notify
+           (USER_SELECTED_INFERIOR
+            | USER_SELECTED_THREAD
+            | USER_SELECTED_FRAME);
+       }
+      else
+       {
+         switch_to_inferior_no_thread (inf);
+
+         gdb::observers::user_selected_context_changed.notify
+           (USER_SELECTED_INFERIOR);
+       }
     }
 }
 
@@ -674,7 +747,6 @@ add_inferior_with_spaces (void)
   struct address_space *aspace;
   struct program_space *pspace;
   struct inferior *inf;
-  struct gdbarch_info info;
 
   /* If all inferiors share an address space on this system, this
      doesn't really return a new address space; otherwise, it
@@ -687,7 +759,7 @@ add_inferior_with_spaces (void)
 
   /* Setup the inferior's initial arch, based on information obtained
      from the global "set ..." options.  */
-  gdbarch_info_init (&info);
+  gdbarch_info info;
   inf->gdbarch = gdbarch_find_by_info (info);
   /* The "set ..." options reject invalid settings, so we should
      always have a valid arch by now.  */
@@ -712,9 +784,22 @@ switch_to_inferior_and_push_target (inferior *new_inf,
 
   /* Reuse the target for new inferior.  */
   if (!no_connection && proc_target != NULL)
-    push_target (proc_target);
-
-  printf_filtered (_("Added inferior %d\n"), new_inf->num);
+    {
+      new_inf->push_target (proc_target);
+      if (proc_target->connection_string () != NULL)
+       printf_filtered (_("Added inferior %d on connection %d (%s %s)\n"),
+                        new_inf->num,
+                        proc_target->connection_number,
+                        proc_target->shortname (),
+                        proc_target->connection_string ());
+      else
+       printf_filtered (_("Added inferior %d on connection %d (%s)\n"),
+                        new_inf->num,
+                        proc_target->connection_number,
+                        proc_target->shortname ());
+    }
+  else
+    printf_filtered (_("Added inferior %d\n"), new_inf->num);
 }
 
 /* add-inferior [-copies N] [-exec FILENAME] [-no-connection] */
@@ -905,8 +990,7 @@ initialize_inferiors (void)
      can only allocate an inferior when all those modules have done
      that.  Do this after initialize_progspace, due to the
      current_program_space reference.  */
-  current_inferior_ = add_inferior_silent (0);
-  current_inferior_->incref ();
+  set_current_inferior (add_inferior_silent (0));
   current_inferior_->pspace = current_program_space;
   current_inferior_->aspace = current_program_space->aspace;
   /* The architecture will be initialized shortly, by
@@ -961,12 +1045,12 @@ The new inferior ID must be currently known."),
           &cmdlist);
 
   add_setshow_boolean_cmd ("inferior-events", no_class,
-         &print_inferior_events, _("\
+        &print_inferior_events, _("\
 Set printing of inferior events (such as inferior start and exit)."), _("\
 Show printing of inferior events (such as inferior start and exit)."), NULL,
-         NULL,
-         show_print_inferior_events,
-         &setprintlist, &showprintlist);
+        NULL,
+        show_print_inferior_events,
+        &setprintlist, &showprintlist);
 
   create_internalvar_type_lazy ("_inferior", &inferior_funcs, NULL);
 }
This page took 0.045621 seconds and 4 git commands to generate.