[PATCH 6 of 8 V5] worker: make sure killworkers runs at most once
Jun Wu
quark at fb.com
Mon Nov 14 21:39:09 EST 2016
# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1479176697 0
# Tue Nov 15 02:24:57 2016 +0000
# Node ID 8402c91c250a9dd369296dcdf00f7b50110ff6ae
# Parent 9dbb3532b173a980f341e41d9e96338a386364e5
# Available At https://bitbucket.org/quark-zju/hg-draft
# hg pull https://bitbucket.org/quark-zju/hg-draft -r 8402c91c250a
worker: make sure killworkers runs at most once
With the next patch adding SIGCHILD handler calling
waitforworkers(blocking=False), the current code could call "killworkers"
multiple times:
if st and not problem[0]:
# at this time, another SIGCHILD happens, killworkers may run twice
problem[0] = st
killworkers()
This patch uses the property that "next(itertools.count())" is an "atomic
test and update" operation at the Python code level (cannot be interrupted
by a Python signal handler). That property is true for both CPython
(confirmed from source code) and PyPy (confirmed by PyPy dev arigato on
freenode #pypy channel).
diff --git a/mercurial/worker.py b/mercurial/worker.py
--- a/mercurial/worker.py
+++ b/mercurial/worker.py
@@ -9,4 +9,5 @@ from __future__ import absolute_import
import errno
+import itertools
import os
import signal
@@ -90,4 +91,5 @@ def _posixworker(ui, func, staticargs, a
signal.signal(signal.SIGINT, signal.SIG_IGN)
pids, problem = set(), [0]
+ problemcount = itertools.count()
def killworkers():
# if one worker bails, there's no good reason to wait for the rest
@@ -114,5 +116,8 @@ def _posixworker(ui, func, staticargs, a
pids.remove(p)
st = _exitstatus(st)
- if st and not problem[0]:
+ # next(itertools.count()) cannot be interrupted by a Python signal
+ # handler - true for both CPython and PyPy. So killworkers() runs
+ # at most once.
+ if st and next(problemcount) == 0:
problem[0] = st
killworkers()
More information about the Mercurial-devel
mailing list