summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2018-04-18 18:38:40 +0900
committerTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2018-04-18 18:38:40 +0900
commit853c54eb5c2251adac80982451a2178b7b7ec4c1 (patch)
treee3f7c57e5bc15438a07069e4f15c7b663f2dc11e
parent3b44740589ee5f6634d877bf2e20b189b7624cff (diff)
downloadbuildstream-853c54eb5c2251adac80982451a2178b7b7ec4c1.tar.gz
_scheduler/job.py: Don't mess with scheduler loop when forking
Instead of unregistering the mainloop handling of SIGTSTP, block it (along with SIGTERM) while forking, clear the signal handlers and then unblock them in the child process; let the parent handle SIGTSTP after unblocking in the main process.
-rw-r--r--buildstream/_scheduler/job.py19
1 files changed, 12 insertions, 7 deletions
diff --git a/buildstream/_scheduler/job.py b/buildstream/_scheduler/job.py
index ab8f39d08..3af9d7f43 100644
--- a/buildstream/_scheduler/job.py
+++ b/buildstream/_scheduler/job.py
@@ -130,15 +130,12 @@ class Job():
# Spawn the process
self._process = Process(target=self._child_action, args=[self._queue])
- # Here we want the following
+ # Block signals which are handled in the main process such that
+ # the child process does not inherit the parent's state, but the main
+ # process will be notified of any signal after we launch the child.
#
- # A.) Child should inherit blocked SIGINT state, it's never handled there
- # B.) Child should not inherit SIGTSTP handled state
- #
- with _signals.blocked([signal.SIGINT], ignore=False):
- self._scheduler.loop.remove_signal_handler(signal.SIGTSTP)
+ with _signals.blocked([signal.SIGINT, signal.SIGTSTP, signal.SIGTERM], ignore=False):
self._process.start()
- self._scheduler.loop.add_signal_handler(signal.SIGTSTP, self._scheduler.suspend_event)
# Wait for it to complete
self._watcher = asyncio.get_child_watcher()
@@ -274,6 +271,14 @@ class Job():
# getting propagated up to the master process
os.setsid()
+ # First set back to the default signal handlers for the signals
+ # we handle, and then clear their blocked state.
+ #
+ signal_list = [signal.SIGTSTP, signal.SIGTERM]
+ for sig in signal_list:
+ signal.signal(sig, signal.SIG_DFL)
+ signal.pthread_sigmask(signal.SIG_UNBLOCK, signal_list)
+
# Assign the queue we passed across the process boundaries
#
# Set the global message handler in this child