gdb/darwin: skip over WIFSTOPPED wait4 status
authorDominique Quatravaux <dominique.quatravaux@epfl.ch>
Thu, 24 Feb 2022 14:23:21 +0000 (09:23 -0500)
committerSimon Marchi <simon.marchi@polymtl.ca>
Thu, 24 Feb 2022 15:48:37 +0000 (10:48 -0500)
On modern Darwin's, there appears to be a new circumstance in which a
MACH_NOTIFY_DEAD_NAME message can be received, and which was not
previously accounted for: to signal the WIFSTOPPED condition in the
debuggee. In that case the debuggee is not dead yet (and in fact,
counting it as dead would cause a zombie leak - A process in such a
state reparents to PID 1, but cannot be killed).

 - Read and ignore such messages (counting on the next exception message
   to let us know of the inferior's new state again)
 - Refactor logging so as to clearly distinguish between the
   MACH_NOTIFY_DEAD_NAME cases (WIFEXITED, WIFSTOPPED, signal, or
   something else), and warn in the last case

Co-authored-by: Louis-He <1726110778@qq.com>
Co-authored-by: Philippe Blain <levraiphilippeblain@gmail.com>
Change-Id: Ie86904a894e9bd154e6b674b1bfbfbaee7fde3e1

gdb/darwin-nat.c

index 8b0ecfd5b772e857b7e42cb1cfcfceaeecda5b36..adbe7474c6876412e8db1c6311c89e9bc8a1ffa3 100644 (file)
@@ -1063,7 +1063,7 @@ darwin_nat_target::decode_message (mach_msg_header_t *hdr,
     }
   else if (hdr->msgh_id == 0x48)
     {
-      /* MACH_NOTIFY_DEAD_NAME: notification for exit.  */
+      /* MACH_NOTIFY_DEAD_NAME: notification for exit *or* WIFSTOPPED.  */
       int res;
 
       res = darwin_decode_notify_message (hdr, &inf);
@@ -1103,15 +1103,34 @@ darwin_nat_target::decode_message (mach_msg_header_t *hdr,
                  return minus_one_ptid;
                }
              if (WIFEXITED (wstatus))
-               status->set_exited (WEXITSTATUS (wstatus));
-             else
+               {
+                 status->set_exited (WEXITSTATUS (wstatus));
+                 inferior_debug (4, _("darwin_wait: pid=%d exit, status=0x%x\n"),
+                                 res_pid, wstatus);
+               }
+             else if (WIFSTOPPED (wstatus))
+               {
+                 /* Ignore stopped state, it will be handled by the next
+                    exception.  */
+                 status->set_ignore ();
+                 inferior_debug (4, _("darwin_wait: pid %d received WIFSTOPPED\n"),
+                                 res_pid);
+                 return minus_one_ptid;
+               }
+             else if (WIFSIGNALED (wstatus))
                {
                  status->set_signalled
                    (gdb_signal_from_host (WTERMSIG (wstatus)));
+                 inferior_debug (4, _("darwin_wait: pid=%d received signal %d\n"),
+                                 res_pid, status->sig());
+               }
+             else
+               {
+                 status->set_ignore ();
+                 warning (_("Unexpected wait status after MACH_NOTIFY_DEAD_NAME "
+                            "notification: 0x%x"), wstatus);
+                 return minus_one_ptid;
                }
-
-             inferior_debug (4, _("darwin_wait: pid=%d exit, status=0x%x\n"),
-                             res_pid, wstatus);
 
              return ptid_t (inf->pid);
            }