summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Schubert <bschubert15@bloomberg.net>2019-12-06 11:43:22 +0000
committerValentin David <valentin.david@codethink.co.uk>2020-03-10 13:19:26 +0100
commit17acbd3dfda90017e2ffcbec73600f61a19f4492 (patch)
tree8e38f56bd724bd06d0d33d42477455672b588a5c
parent0721ffde2255dfa292626d1779877e72cff78ab4 (diff)
downloadbuildstream-17acbd3dfda90017e2ffcbec73600f61a19f4492.tar.gz
scheduler.py: Only run thread-safe code in callbacks from watchers
Per https://docs.python.org/3/library/asyncio-policy.html#asyncio.AbstractChildWatcher.add_child_handler, the callback from a child handler must be thread safe. Not all our callbacks were. This changes all our callbacks to schedule a call for the next loop iteration instead of executing it directly.
-rw-r--r--buildstream/_scheduler/jobs/job.py8
1 files changed, 7 insertions, 1 deletions
diff --git a/buildstream/_scheduler/jobs/job.py b/buildstream/_scheduler/jobs/job.py
index cbe41bcd1..67ec75db5 100644
--- a/buildstream/_scheduler/jobs/job.py
+++ b/buildstream/_scheduler/jobs/job.py
@@ -138,7 +138,13 @@ class Job():
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)
+
+ # Here we delay the call to the next loop tick. This is in order to be running
+ # in the main thread, as the callback itself must be thread safe.
+ def on_completion(pid, returncode):
+ asyncio.get_event_loop().call_soon(self._parent_child_completed, pid, returncode)
+
+ watcher.add_child_handler(self._process.pid, on_completion)
# terminate()
#