Add a maybe-open-debugger helper
parent
fb026e3747
commit
c02a493d8c
|
@ -239,7 +239,8 @@ async def _hijack_stdin_for_child(
|
||||||
subactor_uid: Tuple[str, str]
|
subactor_uid: Tuple[str, str]
|
||||||
|
|
||||||
) -> str:
|
) -> str:
|
||||||
'''Hijack the tty in the root process of an actor tree such that
|
'''
|
||||||
|
Hijack the tty in the root process of an actor tree such that
|
||||||
the pdbpp debugger console can be allocated to a sub-actor for repl
|
the pdbpp debugger console can be allocated to a sub-actor for repl
|
||||||
bossing.
|
bossing.
|
||||||
|
|
||||||
|
@ -274,6 +275,7 @@ async def _hijack_stdin_for_child(
|
||||||
# assert await stream.receive() == 'pdb_unlock'
|
# assert await stream.receive() == 'pdb_unlock'
|
||||||
|
|
||||||
except (
|
except (
|
||||||
|
# BaseException,
|
||||||
trio.MultiError,
|
trio.MultiError,
|
||||||
trio.BrokenResourceError,
|
trio.BrokenResourceError,
|
||||||
trio.Cancelled, # by local cancellation
|
trio.Cancelled, # by local cancellation
|
||||||
|
@ -289,8 +291,9 @@ async def _hijack_stdin_for_child(
|
||||||
|
|
||||||
if isinstance(err, trio.Cancelled):
|
if isinstance(err, trio.Cancelled):
|
||||||
raise
|
raise
|
||||||
|
finally:
|
||||||
log.debug(f"TTY lock released, remote task: {task_name}:{subactor_uid}")
|
log.pdb("TTY lock released, remote task:"
|
||||||
|
f"{task_name}:{subactor_uid}")
|
||||||
|
|
||||||
return "pdb_unlock_complete"
|
return "pdb_unlock_complete"
|
||||||
|
|
||||||
|
@ -433,11 +436,10 @@ async def _breakpoint(
|
||||||
if stats.owner:
|
if stats.owner:
|
||||||
print(f'LOCK STATS: {stats}')
|
print(f'LOCK STATS: {stats}')
|
||||||
|
|
||||||
# with trio.CancelScope(shield=True):
|
|
||||||
# must shield here to avoid hitting a ``Cancelled`` and
|
# must shield here to avoid hitting a ``Cancelled`` and
|
||||||
# a child getting stuck bc we clobbered the tty
|
# a child getting stuck bc we clobbered the tty
|
||||||
await _debug_lock.acquire()
|
with trio.CancelScope(shield=True):
|
||||||
|
await _debug_lock.acquire()
|
||||||
else:
|
else:
|
||||||
# may be cancelled
|
# may be cancelled
|
||||||
await _debug_lock.acquire()
|
await _debug_lock.acquire()
|
||||||
|
@ -535,3 +537,56 @@ async def _maybe_enter_pm(err):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
async def maybe_wait_for_debugger() -> None:
|
||||||
|
|
||||||
|
global _no_remote_has_tty, _global_actor_in_debug
|
||||||
|
|
||||||
|
# If we error in the root but the debugger is
|
||||||
|
# engaged we don't want to prematurely kill (and
|
||||||
|
# thus clobber access to) the local tty since it
|
||||||
|
# will make the pdb repl unusable.
|
||||||
|
# Instead try to wait for pdb to be released before
|
||||||
|
# tearing down.
|
||||||
|
if (
|
||||||
|
_state.debug_mode() and
|
||||||
|
is_root_process()
|
||||||
|
):
|
||||||
|
|
||||||
|
# TODO: could this make things more deterministic?
|
||||||
|
# wait to see if a sub-actor task will be
|
||||||
|
# scheduled and grab the tty lock on the next
|
||||||
|
# tick?
|
||||||
|
# await trio.testing.wait_all_tasks_blocked()
|
||||||
|
|
||||||
|
sub_in_debug = None
|
||||||
|
if _global_actor_in_debug:
|
||||||
|
sub_in_debug = tuple(_global_actor_in_debug)
|
||||||
|
|
||||||
|
for _ in range(2):
|
||||||
|
with trio.CancelScope(shield=True):
|
||||||
|
|
||||||
|
log.warning(
|
||||||
|
'Root polling for debug')
|
||||||
|
await trio.sleep(0.01)
|
||||||
|
|
||||||
|
debug_complete = _no_remote_has_tty
|
||||||
|
if (
|
||||||
|
(debug_complete and
|
||||||
|
not debug_complete.is_set())
|
||||||
|
):
|
||||||
|
log.warning(
|
||||||
|
'Root has errored but pdb is in use by '
|
||||||
|
f'child {sub_in_debug}\n'
|
||||||
|
'Waiting on tty lock to release..')
|
||||||
|
|
||||||
|
await debug_complete.wait()
|
||||||
|
|
||||||
|
await trio.sleep(0.01)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
log.warning(
|
||||||
|
'Root acquired DEBUGGER'
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
Loading…
Reference in New Issue