Bug 1329528 - Reap zombie processes on Mac OS if killing the process group initially fails with EPERM. r=ahal, a=test-only
authorSam Giles <sam.e.giles@gmail.com>
Thu, 16 Feb 2017 06:18:17 +0000
changeset 378615 63baf28e129ecef33ff1b21facd6c20456fc5939
parent 378614 2022fb5a3a0e27893bf1749def685a0cb47dcc8c
child 378616 fd856899995a8f67c2acf572f571961685157ace
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahal, test-only
bugs1329528
milestone53.0a2
Bug 1329528 - Reap zombie processes on Mac OS if killing the process group initially fails with EPERM. r=ahal, a=test-only MozReview-Commit-ID: IKqXKIN0mXx
testing/mozbase/mozprocess/mozprocess/processhandler.py
--- a/testing/mozbase/mozprocess/mozprocess/processhandler.py
+++ b/testing/mozbase/mozprocess/mozprocess/processhandler.py
@@ -147,22 +147,34 @@ class ProcessHandlerMixin(object):
                         winprocess.TerminateProcess(self._handle, winprocess.ERROR_CONTROL_C_EXIT)
                     except:
                         traceback.print_exc()
                         raise OSError("Could not terminate process")
                     finally:
                         winprocess.GetExitCodeProcess(self._handle)
                         self._cleanup()
             else:
-                def send_sig(sig):
+                def send_sig(sig, retries=0):
                     pid = self.detached_pid or self.pid
                     if not self._ignore_children:
                         try:
                             os.killpg(pid, sig)
                         except BaseException as e:
+                            # On Mac OSX if the process group contains zombie
+                            # processes, killpg results in an EPERM.
+                            # In this case, zombie processes need to be reaped
+                            # before continuing
+                            # Note: A negative pid refers to the entire process
+                            # group
+                            if retries < 1 and getattr(e, "errno", None) == errno.EPERM:
+                                try:
+                                    os.waitpid(-pid, 0)
+                                finally:
+                                    return send_sig(sig, retries + 1)
+
                             # ESRCH is a "no such process" failure, which is fine because the
                             # application might already have been terminated itself. Any other
                             # error would indicate a problem in killing the process.
                             if getattr(e, "errno", None) != errno.ESRCH:
                                 print >> sys.stderr, "Could not terminate process: %s" % self.pid
                                 raise
                     else:
                         os.kill(pid, sig)