summaryrefslogtreecommitdiff
path: root/src/buildstream/_signals.py
diff options
context:
space:
mode:
authorBenjamin Schubert <contact@benschubert.me>2020-06-17 20:57:37 +0000
committerBenjamin Schubert <contact@benschubert.me>2020-06-23 18:56:53 +0000
commitcd3d7c08f7c21c47ca51278521477fb10448cdbe (patch)
treee932ea278156295b2d84f8018fbca0b64dd18dd3 /src/buildstream/_signals.py
parente4e3b4568e6f7e1575fdd90ec2c688ceee97322e (diff)
downloadbuildstream-bschubert/signals.tar.gz
_signals.py: allow calling signal handler from non-main threadsbschubert/signals
This modifies the signal terminator so that it can be called from any thread. This checks that either: - The signal handler is already in place - Or the caller is in the main thread, allowing to set the signal handler. This also removes the exact callback that was added instead of removing the last one, and fixes the `suspend_handler` to do the same. This is required, as we don't know which interleaving of calls will be done, and we can't guarantee that the last one is the right one to remove
Diffstat (limited to 'src/buildstream/_signals.py')
-rw-r--r--src/buildstream/_signals.py13
1 files changed, 6 insertions, 7 deletions
diff --git a/src/buildstream/_signals.py b/src/buildstream/_signals.py
index 03b55b052..1edd445b6 100644
--- a/src/buildstream/_signals.py
+++ b/src/buildstream/_signals.py
@@ -80,13 +80,10 @@ def terminator_handler(signal_, frame):
def terminator(terminate_func):
global terminator_stack # pylint: disable=global-statement
- # Signal handling only works in the main thread
- if threading.current_thread() != threading.main_thread():
- yield
- return
-
outermost = bool(not terminator_stack)
+ assert threading.current_thread() == threading.main_thread() or not outermost
+
terminator_stack.append(terminate_func)
if outermost:
original_handler = signal.signal(signal.SIGTERM, terminator_handler)
@@ -96,7 +93,7 @@ def terminator(terminate_func):
finally:
if outermost:
signal.signal(signal.SIGTERM, original_handler)
- terminator_stack.pop()
+ terminator_stack.remove(terminate_func)
# Just a simple object for holding on to two callbacks
@@ -146,6 +143,8 @@ def suspendable(suspend_callback, resume_callback):
global suspendable_stack # pylint: disable=global-statement
outermost = bool(not suspendable_stack)
+ assert threading.current_thread() == threading.main_thread() or not outermost
+
suspender = Suspender(suspend_callback, resume_callback)
suspendable_stack.append(suspender)
@@ -158,7 +157,7 @@ def suspendable(suspend_callback, resume_callback):
if outermost:
signal.signal(signal.SIGTSTP, original_stop)
- suspendable_stack.pop()
+ suspendable_stack.remove(suspender)
# blocked()