From patchwork Tue Nov 15 02:39:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [6,of,8,V5] worker: make sure killworkers runs at most once From: Jun Wu X-Patchwork-Id: 17580 Message-Id: <8402c91c250a9dd36929.1479177549@x1c> To: Date: Tue, 15 Nov 2016 02:39:09 +0000 # HG changeset patch # User Jun Wu # 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()