Fix crash in "run" on macOS when gdb is not signed
authorTom Tromey <tom@tromey.com>
Thu, 28 Jun 2018 17:57:39 +0000 (11:57 -0600)
committerTom Tromey <tom@tromey.com>
Tue, 3 Jul 2018 15:28:26 +0000 (09:28 -0600)
On macOS, when gdb is not code-signed, it will throw an exception from
darwin_attach_pid.  However, gdb also then crashes:

thread.c:93: internal-error: struct thread_info *inferior_thread(): Assertion `tp' failed.

I think the problem here is that darwin_attach_pid does not clean up
inferior_ptid and inf->pid on failure.  This leads to a situation
where gdb tries to find a thread, but cannot.

In other cases, gdb would mourn the inferior at this point; but here
this is not possible because the target has not been pushed.  Instead
this patch works by simply updating the inferior and inferior_ptid on
failure.

Tested by building an unsigned gdb on macOS and trying to run an
inferior.

gdb/ChangeLog
2018-07-03  Tom Tromey  <tom@tromey.com>

PR cli/23340:
* darwin-nat.c (darwin_attach_pid): Reset inferior and
inferior_ptid on error.

gdb/ChangeLog
gdb/darwin-nat.c

index 7bb41008327481df02f4965e0f049f06ae9c1efd..8ecf370e599382fa9a01b77de7b7201ee8b25624 100644 (file)
@@ -1,3 +1,9 @@
+2018-07-03  Tom Tromey  <tom@tromey.com>
+
+       PR cli/23340:
+       * darwin-nat.c (darwin_attach_pid): Reset inferior and
+       inferior_ptid on error.
+
 2018-07-02  Maciej W. Rozycki  <macro@mips.com>
            Simon Marchi  <simon.marchi@polymtl.ca>
 
index 7dccce7392674aefa5ead321266f20aa37ed85f9..6fb108846d0b921fb09ff585832843c9faf66946 100644 (file)
@@ -1583,77 +1583,92 @@ darwin_attach_pid (struct inferior *inf)
   darwin_inferior *priv = new darwin_inferior;
   inf->priv.reset (priv);
 
-  kret = task_for_pid (gdb_task, inf->pid, &priv->task);
-  if (kret != KERN_SUCCESS)
+  TRY
     {
-      int status;
-
-      if (!inf->attach_flag)
+      kret = task_for_pid (gdb_task, inf->pid, &priv->task);
+      if (kret != KERN_SUCCESS)
        {
-         kill (inf->pid, 9);
-         waitpid (inf->pid, &status, 0);
-       }
+         int status;
+
+         if (!inf->attach_flag)
+           {
+             kill (inf->pid, 9);
+             waitpid (inf->pid, &status, 0);
+           }
 
-      error (_("Unable to find Mach task port for process-id %d: %s (0x%lx).\n"
+         error
+           (_("Unable to find Mach task port for process-id %d: %s (0x%lx).\n"
               " (please check gdb is codesigned - see taskgated(8))"),
-             inf->pid, mach_error_string (kret), (unsigned long) kret);
-    }
+            inf->pid, mach_error_string (kret), (unsigned long) kret);
+       }
 
-  inferior_debug (2, _("inferior task: 0x%x, pid: %d\n"),
-                 priv->task, inf->pid);
+      inferior_debug (2, _("inferior task: 0x%x, pid: %d\n"),
+                     priv->task, inf->pid);
 
-  if (darwin_ex_port == MACH_PORT_NULL)
-    {
-      /* Create a port to get exceptions.  */
-      kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE,
-                                &darwin_ex_port);
-      if (kret != KERN_SUCCESS)
-       error (_("Unable to create exception port, mach_port_allocate "
-                "returned: %d"),
-              kret);
+      if (darwin_ex_port == MACH_PORT_NULL)
+       {
+         /* Create a port to get exceptions.  */
+         kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE,
+                                    &darwin_ex_port);
+         if (kret != KERN_SUCCESS)
+           error (_("Unable to create exception port, mach_port_allocate "
+                    "returned: %d"),
+                  kret);
 
-      kret = mach_port_insert_right (gdb_task, darwin_ex_port, darwin_ex_port,
-                                    MACH_MSG_TYPE_MAKE_SEND);
-      if (kret != KERN_SUCCESS)
-       error (_("Unable to create exception port, mach_port_insert_right "
-                "returned: %d"),
-              kret);
+         kret = mach_port_insert_right (gdb_task, darwin_ex_port,
+                                        darwin_ex_port,
+                                        MACH_MSG_TYPE_MAKE_SEND);
+         if (kret != KERN_SUCCESS)
+           error (_("Unable to create exception port, mach_port_insert_right "
+                    "returned: %d"),
+                  kret);
 
-      /* Create a port set and put ex_port in it.  */
-      kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_PORT_SET,
-                                &darwin_port_set);
+         /* Create a port set and put ex_port in it.  */
+         kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_PORT_SET,
+                                    &darwin_port_set);
+         if (kret != KERN_SUCCESS)
+           error (_("Unable to create port set, mach_port_allocate "
+                    "returned: %d"),
+                  kret);
+
+         kret = mach_port_move_member (gdb_task, darwin_ex_port,
+                                       darwin_port_set);
+         if (kret != KERN_SUCCESS)
+           error (_("Unable to move exception port into new port set, "
+                    "mach_port_move_member\n"
+                    "returned: %d"),
+                  kret);
+       }
+
+      /* Create a port to be notified when the child task terminates.  */
+      kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE,
+                                &priv->notify_port);
       if (kret != KERN_SUCCESS)
-       error (_("Unable to create port set, mach_port_allocate "
+       error (_("Unable to create notification port, mach_port_allocate "
                 "returned: %d"),
               kret);
 
-      kret = mach_port_move_member (gdb_task, darwin_ex_port, darwin_port_set);
+      kret = mach_port_move_member (gdb_task,
+                                   priv->notify_port, darwin_port_set);
       if (kret != KERN_SUCCESS)
-       error (_("Unable to move exception port into new port set, "
+       error (_("Unable to move notification port into new port set, "
                 "mach_port_move_member\n"
                 "returned: %d"),
               kret);
-    }
-
-  /* Create a port to be notified when the child task terminates.  */
-  kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE,
-                            &priv->notify_port);
-  if (kret != KERN_SUCCESS)
-    error (_("Unable to create notification port, mach_port_allocate "
-            "returned: %d"),
-          kret);
 
-  kret = mach_port_move_member (gdb_task,
-                               priv->notify_port, darwin_port_set);
-  if (kret != KERN_SUCCESS)
-    error (_("Unable to move notification port into new port set, "
-            "mach_port_move_member\n"
-            "returned: %d"),
-          kret);
+      darwin_setup_request_notification (inf);
 
-  darwin_setup_request_notification (inf);
+      darwin_setup_exceptions (inf);
+    }
+  CATCH (ex, RETURN_MASK_ALL)
+    {
+      inf->pid = 0;
+      inf->priv.reset ();
+      inferior_ptid = null_ptid;
 
-  darwin_setup_exceptions (inf);
+      throw_exception (ex);
+    }
+  END_CATCH
 
   target_ops *darwin_ops = get_native_target ();
   if (!target_is_pushed (darwin_ops))