[PATCH 6 of 8 V4] worker: make killworkers safe to be called multiple times

Yuya Nishihara yuya at tcha.org
Mon Nov 14 08:03:45 EST 2016


On Sat, 12 Nov 2016 03:11:37 +0000, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu <quark at fb.com>
> # Date 1478919468 0
> #      Sat Nov 12 02:57:48 2016 +0000
> # Node ID 596cee9d5c12dcfa2d272b5441d5060a26a6440c
> # Parent  ca128e326027530210f6509e3ec8b28b97bdce12
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #              hg pull https://bitbucket.org/quark-zju/hg-draft -r 596cee9d5c12
> worker: make killworkers safe to be called multiple times

[...]

> --- a/mercurial/worker.py
> +++ b/mercurial/worker.py
> @@ -89,5 +89,14 @@ def _posixworker(ui, func, staticargs, a
>      def killworkers():
>          # if one worker bails, there's no good reason to wait for the rest
> -        for p in pids:
> +        # note: use "while pids" instead of "for p in pids" as other code may
> +        # get run by a signal handler and change "pids" in the mean time.
> +        while pids:
> +            try:
> +                # note: set.pop() cannot be interrupted by a Python signal
> +                # handler - this is true for both cpython and pypy. we use this
> +                # property to make sure a child receive the signal once.
> +                p = pids.pop()
> +            except KeyError:
> +                break # pids is empty
>              try:
>                  os.kill(p, signal.SIGTERM)

The process "p" is about to be killed but removed from the pids set, which
would mean we can't wait killed processes at cleanup().

> @@ -109,5 +118,8 @@ def _posixworker(ui, func, staticargs, a
>                          raise
>              if p:
> -                pids.remove(p)
> +                try:
> +                    pids.remove(p)
> +                except KeyError: # in case p was poped by "killworkers"
> +                    pass


More information about the Mercurial-devel mailing list