diff options
author | Benjamin Schubert <bschubert15@bloomberg.net> | 2019-12-06 11:17:02 +0000 |
---|---|---|
committer | Valentin David <valentin.david@codethink.co.uk> | 2020-03-10 13:16:55 +0100 |
commit | 0721ffde2255dfa292626d1779877e72cff78ab4 (patch) | |
tree | b85378c9466e8d7391d35a831baac24961c46efc | |
parent | 1e7e90ec4f298a948676fae33b5694f2eaa9381f (diff) | |
download | buildstream-0721ffde2255dfa292626d1779877e72cff78ab4.tar.gz |
job.py: Only start new jobs in a `with watcher:` block
The documentation
(https://docs.python.org/3/library/asyncio-policy.html#asyncio.AbstractChildWatcher)
is apparently missing this part, but the code mentions that new
processes should only ever be called inside a with block:
https://github.com/python/cpython/blob/99eb70a9eb9493602ff6ad8bb92df4318cf05a3e/Lib/asyncio/unix_events.py#L808
-rw-r--r-- | buildstream/_scheduler/jobs/job.py | 31 |
1 files changed, 5 insertions, 26 deletions
diff --git a/buildstream/_scheduler/jobs/job.py b/buildstream/_scheduler/jobs/job.py index bf0646a31..cbe41bcd1 100644 --- a/buildstream/_scheduler/jobs/job.py +++ b/buildstream/_scheduler/jobs/job.py @@ -1,5 +1,6 @@ # # Copyright (C) 2018 Codethink Limited +# Copyright (C) 2019 Bloomberg Finance LP # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -134,32 +135,10 @@ class Job(): # process will be notified of any signal after we launch the child. # with _signals.blocked([signal.SIGINT, signal.SIGTSTP, signal.SIGTERM], ignore=False): - self._process.start() - - # Wait for the child task to complete. - # - # This is a tricky part of python which doesnt seem to - # make it to the online docs: - # - # o asyncio.get_child_watcher() will return a SafeChildWatcher() instance - # which is the default type of watcher, and the instance belongs to the - # "event loop policy" in use (so there is only one in the main process). - # - # o SafeChildWatcher() will register a SIGCHLD handler with the asyncio - # loop, and will selectively reap any child pids which have been - # terminated. - # - # o At registration time, the process will immediately be checked with - # `os.waitpid()` and will be reaped immediately, before add_child_handler() - # returns. - # - # The self._parent_child_completed callback passed here will normally - # be called after the child task has been reaped with `os.waitpid()`, in - # an event loop callback. Otherwise, if the job completes too fast, then - # the callback is called immediately. - # - self._watcher = asyncio.get_child_watcher() - self._watcher.add_child_handler(self._process.pid, self._parent_child_completed) + with asyncio.get_child_watcher() as watcher: + self._process.start() + # Register the process to call `_parent_child_completed` once it is done + watcher.add_child_handler(self._process.pid, self._parent_child_completed) # terminate() # |