worker: add a SIGCHLD handler to collect worker immediately
authorJun Wu <quark@fb.com>
Sat, 12 Nov 2016 03:07:22 +0000
changeset 30415 e8fb03cfbbde
parent 30414 5069a8a40b1b
child 30416 c27614f2dec1
worker: add a SIGCHLD handler to collect worker immediately As planned by previous patches, add a SIGCHLD handler to get notifications about worker exits, and deals with worker failure immediately. Note that the SIGCHLD handler gets unregistered before killworkers(), so SIGCHLD won't interrupt "killworkers" - making it harder to send kill signals to waited processes.
mercurial/worker.py
--- a/mercurial/worker.py	Tue Nov 15 02:12:16 2016 +0000
+++ b/mercurial/worker.py	Sat Nov 12 03:07:22 2016 +0000
@@ -115,11 +115,17 @@
                 st = _exitstatus(st)
             if st and not problem[0]:
                 problem[0] = st
+                # unregister SIGCHLD handler as all children will be killed
+                signal.signal(signal.SIGCHLD, oldchldhandler)
                 killworkers()
+    def sigchldhandler(signum, frame):
+        waitforworkers(blocking=False)
+    oldchldhandler = signal.signal(signal.SIGCHLD, sigchldhandler)
     for pargs in partition(args, workers):
         pid = os.fork()
         if pid == 0:
             signal.signal(signal.SIGINT, oldhandler)
+            signal.signal(signal.SIGCHLD, oldchldhandler)
             try:
                 os.close(rfd)
                 for i, item in func(*(staticargs + (pargs,))):
@@ -137,6 +143,7 @@
     def cleanup():
         signal.signal(signal.SIGINT, oldhandler)
         t.join()
+        signal.signal(signal.SIGCHLD, oldchldhandler)
         status = problem[0]
         if status:
             if status < 0: