summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2018-06-26 19:40:28 -0400
committerTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2018-06-26 19:40:28 -0400
commit91d87e3c901dd9ac2cd3e7d148e5313cc5b915b0 (patch)
tree5d90a34d02962141d8acea6fe7c423c21a3ac715
parenta25d683e54159cd92c21ceab793c6966ca99b6d6 (diff)
downloadbuildstream-91d87e3c901dd9ac2cd3e7d148e5313cc5b915b0.tar.gz
_scheduler/job.py: Added long comment
This explains the nature of a complicated asyncio callback, which I've looked up on multiple occasions and is not available in python online docs (only in the source can you follow it).
-rw-r--r--buildstream/_scheduler/job.py23
1 files changed, 22 insertions, 1 deletions
diff --git a/buildstream/_scheduler/job.py b/buildstream/_scheduler/job.py
index 8b9af9393..cc350649e 100644
--- a/buildstream/_scheduler/job.py
+++ b/buildstream/_scheduler/job.py
@@ -137,7 +137,28 @@ class Job():
with _signals.blocked([signal.SIGINT, signal.SIGTSTP, signal.SIGTERM], ignore=False):
self._process.start()
- # Wait for it to complete
+ # 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)