forked from goodboy/tractor
Support `maybe_wait_for_debugger(header_msg: str)`
Allow callers to stick in a header to the `.pdb()` level emitted msg(s) such that any "waiting status" content is only shown if the caller actually get's blocked waiting for the debug lock; use it inside the `._spawn` sub-process reaper call. Also, return early if `Lock.global_actor_in_debug == None` and thus only enter the poll loop when actually needed, consequently raise if we fall through the loop without acquisition.modden_spawn_from_client_req
parent
de1843dc84
commit
fc72d75061
|
@ -541,13 +541,14 @@ async def trio_proc(
|
||||||
with trio.move_on_after(0.5):
|
with trio.move_on_after(0.5):
|
||||||
await proc.wait()
|
await proc.wait()
|
||||||
|
|
||||||
log.pdb(
|
|
||||||
'Delaying subproc reaper while debugger locked..'
|
|
||||||
)
|
|
||||||
await maybe_wait_for_debugger(
|
await maybe_wait_for_debugger(
|
||||||
child_in_debug=_runtime_vars.get(
|
child_in_debug=_runtime_vars.get(
|
||||||
'_debug_mode', False
|
'_debug_mode', False
|
||||||
),
|
),
|
||||||
|
header_msg=(
|
||||||
|
'Delaying subproc reaper while debugger locked..\n'
|
||||||
|
),
|
||||||
|
|
||||||
# TODO: need a diff value then default?
|
# TODO: need a diff value then default?
|
||||||
# poll_steps=9999999,
|
# poll_steps=9999999,
|
||||||
)
|
)
|
||||||
|
|
|
@ -999,6 +999,8 @@ async def maybe_wait_for_debugger(
|
||||||
poll_delay: float = 0.1,
|
poll_delay: float = 0.1,
|
||||||
child_in_debug: bool = False,
|
child_in_debug: bool = False,
|
||||||
|
|
||||||
|
header_msg: str = '',
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -1007,6 +1009,8 @@ async def maybe_wait_for_debugger(
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
msg: str = header_msg
|
||||||
if (
|
if (
|
||||||
is_root_process()
|
is_root_process()
|
||||||
):
|
):
|
||||||
|
@ -1016,48 +1020,59 @@ async def maybe_wait_for_debugger(
|
||||||
# will make the pdb repl unusable.
|
# will make the pdb repl unusable.
|
||||||
# Instead try to wait for pdb to be released before
|
# Instead try to wait for pdb to be released before
|
||||||
# tearing down.
|
# tearing down.
|
||||||
sub_in_debug: tuple[str, str] | None = None
|
sub_in_debug: tuple[str, str]|None = Lock.global_actor_in_debug
|
||||||
|
debug_complete: trio.Event|None = Lock.no_remote_has_tty
|
||||||
|
|
||||||
|
if sub_in_debug := Lock.global_actor_in_debug:
|
||||||
|
msg += (
|
||||||
|
'Debug `Lock` in use by subactor\n'
|
||||||
|
f'|_{sub_in_debug}\n'
|
||||||
|
)
|
||||||
|
# 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?
|
||||||
|
# XXX => but it doesn't seem to work..
|
||||||
|
# await trio.testing.wait_all_tasks_blocked(cushion=0)
|
||||||
|
else:
|
||||||
|
log.pdb(
|
||||||
|
msg
|
||||||
|
+
|
||||||
|
'Root immediately acquired debug TTY LOCK'
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
for istep in range(poll_steps):
|
for istep in range(poll_steps):
|
||||||
|
|
||||||
if sub_in_debug := Lock.global_actor_in_debug:
|
|
||||||
log.pdb(
|
|
||||||
f'Lock in use by {sub_in_debug}'
|
|
||||||
)
|
|
||||||
# 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?
|
|
||||||
# XXX => but it doesn't seem to work..
|
|
||||||
# await trio.testing.wait_all_tasks_blocked(cushion=0)
|
|
||||||
|
|
||||||
debug_complete: trio.Event|None = Lock.no_remote_has_tty
|
|
||||||
if (
|
if (
|
||||||
debug_complete
|
debug_complete
|
||||||
and not debug_complete.is_set()
|
and not debug_complete.is_set()
|
||||||
and sub_in_debug is not None
|
and sub_in_debug is not None
|
||||||
):
|
):
|
||||||
log.pdb(
|
log.pdb(
|
||||||
'Root has errored but pdb is in use by child\n'
|
msg
|
||||||
'Waiting on tty lock to release..\n'
|
+
|
||||||
f'uid: {sub_in_debug}\n'
|
'Root is waiting on tty lock to release..\n'
|
||||||
)
|
)
|
||||||
await debug_complete.wait()
|
await debug_complete.wait()
|
||||||
log.pdb(
|
log.pdb(
|
||||||
f'Child subactor released debug lock!\n'
|
f'Child subactor released debug lock:'
|
||||||
f'uid: {sub_in_debug}\n'
|
f'|_{sub_in_debug}\n'
|
||||||
)
|
)
|
||||||
if debug_complete.is_set():
|
|
||||||
break
|
|
||||||
|
|
||||||
# is no subactor locking debugger currently?
|
# is no subactor locking debugger currently?
|
||||||
elif (
|
if (
|
||||||
debug_complete is None
|
sub_in_debug is None
|
||||||
or sub_in_debug is None
|
and (
|
||||||
|
debug_complete is None
|
||||||
|
or debug_complete.is_set()
|
||||||
|
)
|
||||||
):
|
):
|
||||||
log.pdb(
|
log.pdb(
|
||||||
'Root acquired debug TTY LOCK from child\n'
|
msg
|
||||||
f'uid: {sub_in_debug}'
|
+
|
||||||
|
'Root acquired tty lock!'
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -1073,8 +1088,14 @@ async def maybe_wait_for_debugger(
|
||||||
with trio.CancelScope(shield=True):
|
with trio.CancelScope(shield=True):
|
||||||
await trio.sleep(poll_delay)
|
await trio.sleep(poll_delay)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# fallthrough on failure to acquire..
|
||||||
else:
|
else:
|
||||||
log.pdb('Root acquired debug TTY LOCK')
|
raise RuntimeError(
|
||||||
|
msg
|
||||||
|
+
|
||||||
|
'Root actor failed to acquire debug lock?'
|
||||||
|
)
|
||||||
|
|
||||||
# else:
|
# else:
|
||||||
# # TODO: non-root call for #320?
|
# # TODO: non-root call for #320?
|
||||||
|
|
Loading…
Reference in New Issue