Patchwork [1,of,3] worker: on error, exit similarly to the first failing worker

login
register
mail settings
Submitter Bryan O'Sullivan
Date Feb. 19, 2013, 6:29 p.m.
Message ID <aa2394d75dcc1fb33f3f.1361298553@australite.local>
Download mbox | patch
Permalink /patch/1031/
State Superseded
Headers show

Comments

Bryan O'Sullivan - Feb. 19, 2013, 6:29 p.m.
# HG changeset patch
# User Bryan O'Sullivan <bryano@fb.com>
# Date 1361297550 28800
# Node ID aa2394d75dcc1fb33f3f548013874acdfbaf845f
# Parent  a326a3b6e3959bba37502a05169cf2797150f4c4
worker: on error, exit similarly to the first failing worker

Previously, if a worker failed, we exited with status 1. We now exit
with the correct exit code (killing ourselves if necessary).
Bryan O'Sullivan - Feb. 19, 2013, 8:54 p.m.
On Tue, Feb 19, 2013 at 10:42 AM, Kevin Bullock <
kbullock+mercurial@ringworld.org> wrote:

> What happens if _exitstatus raises a ValueError here?
>

Good point - fixed in v2.

Patch

diff --git a/mercurial/worker.py b/mercurial/worker.py
--- a/mercurial/worker.py
+++ b/mercurial/worker.py
@@ -92,11 +92,15 @@  def _posixworker(ui, func, staticargs, a
     def cleanup():
         # python 2.4 is too dumb for try/yield/finally
         signal.signal(signal.SIGINT, oldhandler)
-        problems = 0
+        problem = None
         for i in xrange(workers):
-            problems |= os.wait()[1]
-        if problems:
-            sys.exit(1)
+            pid, st = os.wait()
+            if st and not problem:
+                problem = _exitstatus(st)
+        if problem:
+            if problem < 0:
+                os.kill(os.getpid(), -problem)
+            sys.exit(problem)
     try:
         for line in fp:
             l = line.split(' ', 1)
@@ -106,8 +110,18 @@  def _posixworker(ui, func, staticargs, a
         raise
     cleanup()
 
+def _posixexitstatus(code):
+    '''convert a posix exit status into the same form returned by
+    os.spawnv'''
+    if os.WIFEXITED(code):
+        return os.WEXITSTATUS(code)
+    elif os.WIFSIGNALED(code):
+        return -os.WTERMSIG(code)
+    raise ValueError('unexpected exit status %d' % code)
+
 if os.name != 'nt':
     _platformworker = _posixworker
+    _exitstatus = _posixexitstatus
 
 def partition(lst, nslices):
     '''partition a list into N slices of equal size'''