diff options
author | Tristan Van Berkom <tristan.vanberkom@codethink.co.uk> | 2018-04-18 18:38:40 +0900 |
---|---|---|
committer | Tristan Van Berkom <tristan.vanberkom@codethink.co.uk> | 2018-04-18 18:38:40 +0900 |
commit | 853c54eb5c2251adac80982451a2178b7b7ec4c1 (patch) | |
tree | e3f7c57e5bc15438a07069e4f15c7b663f2dc11e | |
parent | 3b44740589ee5f6634d877bf2e20b189b7624cff (diff) | |
download | buildstream-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.py | 19 |
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 |