-
Notifications
You must be signed in to change notification settings - Fork 10
Register existing signal handlers in simpervisor's atexit module #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
5999f60
b52fd8d
7e17032
7b3dd30
15304ee
0c1be62
4d2e774
3461767
e1265cd
0788834
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,27 +8,69 @@ | |
|
||
_handlers = [] | ||
|
||
_prev_handlers = {} | ||
signal_handler_set = False | ||
|
||
|
||
def add_handler(handler): | ||
global signal_handler_set | ||
if not signal_handler_set: | ||
signal.signal(signal.SIGINT, _handle_signal) | ||
signal.signal(signal.SIGTERM, _handle_signal) | ||
signal_handler_set = True | ||
""" | ||
Adds a signal handler function that will be called when the Python process | ||
receives either a SIGINT (on windows CTRL_C_EVENT) or SIGTERM signal. | ||
""" | ||
_ensure_signal_handlers_set() | ||
_handlers.append(handler) | ||
|
||
|
||
def remove_handler(handler): | ||
"""Removes previously added signal handler.""" | ||
_handlers.remove(handler) | ||
|
||
|
||
def _ensure_signal_handlers_set(): | ||
""" | ||
Ensures _handle_signal is registered as a top level signal handler for | ||
SIGINT and SIGTERM and saves previously registered non-default Python | ||
callable signal handlers. | ||
""" | ||
global signal_handler_set | ||
if not signal_handler_set: | ||
# save previously registered non-default Python callable signal handlers | ||
# | ||
# windows note: signal.getsignal(signal.CTRL_C_EVENT) would error with | ||
# "ValueError: signal number out of range", and | ||
# signal.signal(signal.CTRL_C_EVENT, _handle_signal) would error with | ||
# "ValueError: invalid signal value". | ||
# | ||
prev_sigint = signal.getsignal(signal.SIGINT) | ||
prev_sigterm = signal.getsignal(signal.SIGTERM) | ||
if callable(prev_sigint) and prev_sigint.__qualname__ != "default_int_handler": | ||
_prev_handlers[signal.SIGINT] = prev_sigint | ||
if callable(prev_sigterm) and prev_sigterm != signal.Handlers.SIG_DFL: | ||
_prev_handlers[signal.SIGTERM] = prev_sigterm | ||
|
||
# let _handle_signal handle SIGINT and SIGTERM | ||
signal.signal(signal.SIGINT, _handle_signal) | ||
signal.signal(signal.SIGTERM, _handle_signal) | ||
signal_handler_set = True | ||
|
||
|
||
def _handle_signal(signum, *args): | ||
""" | ||
Calls functions added by add_handler, and then calls the previously | ||
registered non-default Python callable signal handler if there were one. | ||
""" | ||
prev_handler = _prev_handlers.get(signum) | ||
|
||
# Windows doesn't support SIGINT. Replacing it with CTRL_C_EVENT so that it | ||
# can used with subprocess.Popen.send_signal | ||
if signum == signal.SIGINT and sys.platform == "win32": | ||
signum = signal.CTRL_C_EVENT | ||
|
||
for handler in _handlers: | ||
handler(signum) | ||
sys.exit(0) | ||
|
||
# call previously registered non-default Python callable handler or exit | ||
if prev_handler: | ||
prev_handler(signum, *args) | ||
Comment on lines
+72
to
+74
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should get review and ideally tested on windows:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
else: | ||
sys.exit(0) |
Uh oh!
There was an error while loading. Please reload this page.