Patchwork [2,of,4] worker: make sure killworkers() never be interrupted by another SIGCHLD

login
register
mail settings
Submitter Yuya Nishihara
Date Nov. 17, 2016, 1:20 p.m.
Message ID <60c9574e29b43c6d9579.1479388800@mimosa>
Download mbox | patch
Permalink /patch/17613/
State Accepted
Headers show

Comments

Yuya Nishihara - Nov. 17, 2016, 1:20 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1479383045 -32400
#      Thu Nov 17 20:44:05 2016 +0900
# Node ID 60c9574e29b43c6d9579b99249ba11ff19af77a0
# Parent  9aef387fa3c32f92a8fc96088bad8c3de4e95aab
worker: make sure killworkers() never be interrupted by another SIGCHLD

killworkers() iterates over pids, which can be updated by SIGCHLD handler.
So we should either copy pids or prevent killworkers() from being interrupted
by SIGCHLD. I chose the latter as it is simpler and can make pids handling
more consistent.

This fixes a possible "set changed size during iteration" error at
killworkers() before cleanup().

Patch

diff --git a/mercurial/worker.py b/mercurial/worker.py
--- a/mercurial/worker.py
+++ b/mercurial/worker.py
@@ -89,6 +89,10 @@  def _posixworker(ui, func, staticargs, a
     signal.signal(signal.SIGINT, signal.SIG_IGN)
     pids, problem = set(), [0]
     def killworkers():
+        # unregister SIGCHLD handler as all children will be killed. This
+        # function shouldn't be interrupted by another SIGCHLD; otherwise pids
+        # could be updated while iterating, which would cause inconsistency.
+        signal.signal(signal.SIGCHLD, oldchldhandler)
         # if one worker bails, there's no good reason to wait for the rest
         for p in pids:
             try:
@@ -115,8 +119,6 @@  def _posixworker(ui, func, staticargs, a
                 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)