forked from goodboy/tractor
Always restore at least `trio`'s sigint handler
We can get it during runtime startup and stash on a new `Lock._trio_handler`. Always at least revert to this handler to guarantee graceful kbi handling despite mucking about with our own handler in debug mode.egs_with_ctx_res_consumption
parent
8727c1e4c2
commit
f6ac0c2eb7
|
@ -75,8 +75,10 @@ class Lock:
|
|||
# placeholder for function to set a ``trio.Event`` on debugger exit
|
||||
# pdb_release_hook: Optional[Callable] = None
|
||||
|
||||
_trio_handler: Callable | None = None
|
||||
|
||||
# actor-wide variable pointing to current task name using debugger
|
||||
local_task_in_debug: Optional[str] = None
|
||||
local_task_in_debug: str | None = None
|
||||
|
||||
# NOTE: set by the current task waiting on the root tty lock from
|
||||
# the CALLER side of the `lock_tty_for_child()` context entry-call
|
||||
|
@ -111,13 +113,10 @@ class Lock:
|
|||
|
||||
@classmethod
|
||||
def unshield_sigint(cls):
|
||||
if cls._orig_sigint_handler is not None:
|
||||
# restore original sigint handler
|
||||
signal.signal(
|
||||
signal.SIGINT,
|
||||
cls._orig_sigint_handler
|
||||
)
|
||||
|
||||
# always restore (some) sigint handler, either
|
||||
# the prior or at least ``trio``'s.
|
||||
orig = cls._orig_sigint_handler or cls._trio_handler
|
||||
signal.signal(signal.SIGINT, orig)
|
||||
cls._orig_sigint_handler = None
|
||||
|
||||
@classmethod
|
||||
|
@ -544,7 +543,7 @@ def shield_sigint(
|
|||
|
||||
) -> None:
|
||||
'''
|
||||
Specialized debugger compatible SIGINT handler.
|
||||
Specialized, debugger-aware SIGINT handler.
|
||||
|
||||
In childred we always ignore to avoid deadlocks since cancellation
|
||||
should always be managed by the parent supervising actor. The root
|
||||
|
@ -601,6 +600,8 @@ def shield_sigint(
|
|||
# which has already terminated to unlock.
|
||||
and any_connected
|
||||
):
|
||||
# we are root and some actor is in debug mode
|
||||
# if uid_in_debug is not None:
|
||||
name = uid_in_debug[0]
|
||||
if name != 'root':
|
||||
log.pdb(
|
||||
|
@ -611,6 +612,22 @@ def shield_sigint(
|
|||
log.pdb(
|
||||
"Ignoring SIGINT while in debug mode"
|
||||
)
|
||||
elif (
|
||||
is_root_process()
|
||||
):
|
||||
log.pdb(
|
||||
"Ignoring SIGINT since debug mode is enabled"
|
||||
)
|
||||
|
||||
# revert back to ``trio`` handler asap!
|
||||
Lock.unshield_sigint()
|
||||
if (
|
||||
Lock._root_local_task_cs_in_debug
|
||||
and not Lock._root_local_task_cs_in_debug.cancel_called
|
||||
):
|
||||
Lock._root_local_task_cs_in_debug.cancel()
|
||||
|
||||
# raise KeyboardInterrupt
|
||||
|
||||
# child actor that has locked the debugger
|
||||
elif not is_root_process():
|
||||
|
@ -636,10 +653,9 @@ def shield_sigint(
|
|||
# https://github.com/goodboy/tractor/issues/320
|
||||
# elif debug_mode():
|
||||
|
||||
else:
|
||||
log.pdb(
|
||||
"Ignoring SIGINT since debug mode is enabled"
|
||||
)
|
||||
else: # XXX: shouldn't ever get here?
|
||||
print("WTFWTFWTF")
|
||||
raise KeyboardInterrupt
|
||||
|
||||
# NOTE: currently (at least on ``fancycompleter`` 0.9.2)
|
||||
# it lookks to be that the last command that was run (eg. ll)
|
||||
|
|
|
@ -23,6 +23,7 @@ from functools import partial
|
|||
import importlib
|
||||
import logging
|
||||
import os
|
||||
import signal
|
||||
from typing import (
|
||||
Optional,
|
||||
)
|
||||
|
@ -76,14 +77,19 @@ async def open_root_actor(
|
|||
rpc_module_paths: Optional[list] = None,
|
||||
|
||||
) -> typing.Any:
|
||||
"""Async entry point for ``tractor``.
|
||||
'''
|
||||
Runtime init entry point for ``tractor``.
|
||||
|
||||
"""
|
||||
'''
|
||||
# Override the global debugger hook to make it play nice with
|
||||
# ``trio``, see:
|
||||
# https://github.com/python-trio/trio/issues/1155#issuecomment-742964018
|
||||
os.environ['PYTHONBREAKPOINT'] = 'tractor._debug._set_trace'
|
||||
|
||||
# attempt to retreive ``trio``'s sigint handler and stash it
|
||||
# on our debugger lock state.
|
||||
_debug.Lock._trio_handler = signal.getsignal(signal.SIGINT)
|
||||
|
||||
# mark top most level process as root actor
|
||||
_state._runtime_vars['_is_root'] = True
|
||||
|
||||
|
|
Loading…
Reference in New Issue