[PATCH 6 of 7 V3] worker: test and set problem[0] atomically

Jun Wu quark at fb.com
Thu Aug 4 14:29:07 EDT 2016


# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1470334096 -3600
#      Thu Aug 04 19:08:16 2016 +0100
# Node ID d08d72f5d8bf302dd1231be410d0b23dc082eb66
# Parent  d179a66b0b15988687ba9d69c5b76e4464a457eb
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r d08d72f5d8bf
worker: test and set problem[0] atomically

Previously problem[0] is not tested and set atomically:

    if st and not problem[0]:
        # at this time, another SIGCHILD happens, killworkers may run twice
        problem[0] = st
        killworkers()

This patch addresses the issue by using itertools.count(). Its CPython
implementation will make it "atomic" at the Python code level, which is
enough for our use-case (signal handler).

diff --git a/mercurial/worker.py b/mercurial/worker.py
--- a/mercurial/worker.py
+++ b/mercurial/worker.py
@@ -8,6 +8,7 @@
 from __future__ import absolute_import
 
 import errno
+import itertools
 import os
 import signal
 import sys
@@ -86,6 +87,7 @@ def _posixworker(ui, func, staticargs, a
     oldhandler = signal.getsignal(signal.SIGINT)
     signal.signal(signal.SIGINT, signal.SIG_IGN)
     pids, problem = [], [0]
+    problemcount = itertools.count()
     def killworkers():
         # if one worker bails, there's no good reason to wait for the rest
         for p in pids:
@@ -107,7 +109,7 @@ def _posixworker(ui, func, staticargs, a
                 break
             if p:
                 st = _exitstatus(st)
-            if st and not problem[0]:
+            if st and next(problemcount) == 0:
                 problem[0] = st
                 killworkers()
     def sigchldhandler(signum, frame):


More information about the Mercurial-devel mailing list