Compare commits
No commits in common. "34bb787d36d1377381974cd6af4347792cc3b406" and "d0a65e8922cf4386b27d3914878cdafba24a23f7" have entirely different histories.
34bb787d36
...
d0a65e8922
|
@ -1,117 +0,0 @@
|
||||||
import asyncio
|
|
||||||
|
|
||||||
import trio
|
|
||||||
import tractor
|
|
||||||
from tractor import to_asyncio
|
|
||||||
|
|
||||||
|
|
||||||
async def aio_sleep_forever():
|
|
||||||
await asyncio.sleep(float('inf'))
|
|
||||||
|
|
||||||
|
|
||||||
async def bp_then_error(
|
|
||||||
to_trio: trio.MemorySendChannel,
|
|
||||||
from_trio: asyncio.Queue,
|
|
||||||
|
|
||||||
raise_after_bp: bool = True,
|
|
||||||
|
|
||||||
) -> None:
|
|
||||||
|
|
||||||
# sync with ``trio``-side (caller) task
|
|
||||||
to_trio.send_nowait('start')
|
|
||||||
|
|
||||||
# NOTE: what happens here inside the hook needs some refinement..
|
|
||||||
# => seems like it's still `._debug._set_trace()` but
|
|
||||||
# we set `Lock.local_task_in_debug = 'sync'`, we probably want
|
|
||||||
# some further, at least, meta-data about the task/actoq in debug
|
|
||||||
# in terms of making it clear it's asyncio mucking about.
|
|
||||||
breakpoint()
|
|
||||||
|
|
||||||
# short checkpoint / delay
|
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
|
|
||||||
if raise_after_bp:
|
|
||||||
raise ValueError('blah')
|
|
||||||
|
|
||||||
# TODO: test case with this so that it gets cancelled?
|
|
||||||
else:
|
|
||||||
# XXX NOTE: this is required in order to get the SIGINT-ignored
|
|
||||||
# hang case documented in the module script section!
|
|
||||||
await aio_sleep_forever()
|
|
||||||
|
|
||||||
|
|
||||||
@tractor.context
|
|
||||||
async def trio_ctx(
|
|
||||||
ctx: tractor.Context,
|
|
||||||
bp_before_started: bool = False,
|
|
||||||
):
|
|
||||||
|
|
||||||
# this will block until the ``asyncio`` task sends a "first"
|
|
||||||
# message, see first line in above func.
|
|
||||||
async with (
|
|
||||||
|
|
||||||
to_asyncio.open_channel_from(
|
|
||||||
bp_then_error,
|
|
||||||
raise_after_bp=not bp_before_started,
|
|
||||||
) as (first, chan),
|
|
||||||
|
|
||||||
trio.open_nursery() as n,
|
|
||||||
):
|
|
||||||
|
|
||||||
assert first == 'start'
|
|
||||||
|
|
||||||
if bp_before_started:
|
|
||||||
await tractor.breakpoint()
|
|
||||||
|
|
||||||
await ctx.started(first)
|
|
||||||
|
|
||||||
n.start_soon(
|
|
||||||
to_asyncio.run_task,
|
|
||||||
aio_sleep_forever,
|
|
||||||
)
|
|
||||||
await trio.sleep_forever()
|
|
||||||
|
|
||||||
|
|
||||||
async def main(
|
|
||||||
bps_all_over: bool = False,
|
|
||||||
|
|
||||||
) -> None:
|
|
||||||
|
|
||||||
async with tractor.open_nursery() as n:
|
|
||||||
|
|
||||||
p = await n.start_actor(
|
|
||||||
'aio_daemon',
|
|
||||||
enable_modules=[__name__],
|
|
||||||
infect_asyncio=True,
|
|
||||||
debug_mode=True,
|
|
||||||
loglevel='cancel',
|
|
||||||
)
|
|
||||||
|
|
||||||
async with p.open_context(
|
|
||||||
trio_ctx,
|
|
||||||
bp_before_started=bps_all_over,
|
|
||||||
) as (ctx, first):
|
|
||||||
|
|
||||||
assert first == 'start'
|
|
||||||
|
|
||||||
if bps_all_over:
|
|
||||||
await tractor.breakpoint()
|
|
||||||
|
|
||||||
# await trio.sleep_forever()
|
|
||||||
await ctx.cancel()
|
|
||||||
assert 0
|
|
||||||
|
|
||||||
# TODO: case where we cancel from trio-side while asyncio task
|
|
||||||
# has debugger lock?
|
|
||||||
# await p.cancel_actor()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
# works fine B)
|
|
||||||
trio.run(main)
|
|
||||||
|
|
||||||
# will hang and ignores SIGINT !!
|
|
||||||
# NOTE: you'll need to send a SIGQUIT (via ctl-\) to kill it
|
|
||||||
# manually..
|
|
||||||
# trio.run(main, True)
|
|
|
@ -1,24 +0,0 @@
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import trio
|
|
||||||
import tractor
|
|
||||||
|
|
||||||
|
|
||||||
async def main() -> None:
|
|
||||||
async with tractor.open_nursery(debug_mode=True) as an:
|
|
||||||
|
|
||||||
assert os.environ['PYTHONBREAKPOINT'] == 'tractor._debug._set_trace'
|
|
||||||
|
|
||||||
# TODO: an assert that verifies the hook has indeed been, hooked
|
|
||||||
# XD
|
|
||||||
assert sys.breakpointhook is not tractor._debug._set_trace
|
|
||||||
|
|
||||||
breakpoint()
|
|
||||||
|
|
||||||
# TODO: an assert that verifies the hook is unhooked..
|
|
||||||
assert sys.breakpointhook
|
|
||||||
breakpoint()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
trio.run(main)
|
|
2
setup.py
2
setup.py
|
@ -61,7 +61,7 @@ setup(
|
||||||
'msgspec',
|
'msgspec',
|
||||||
|
|
||||||
# debug mode REPL
|
# debug mode REPL
|
||||||
'pdbp',
|
'pdbpp',
|
||||||
|
|
||||||
# pip ref docs on these specs:
|
# pip ref docs on these specs:
|
||||||
# https://pip.pypa.io/en/stable/reference/requirement-specifiers/#examples
|
# https://pip.pypa.io/en/stable/reference/requirement-specifiers/#examples
|
||||||
|
|
|
@ -158,16 +158,12 @@ class Lock:
|
||||||
|
|
||||||
class TractorConfig(pdbp.DefaultConfig):
|
class TractorConfig(pdbp.DefaultConfig):
|
||||||
'''
|
'''
|
||||||
Custom ``pdbp`` goodness :surfer:
|
Custom ``pdbp`` goodness.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
use_pygments: bool = True
|
# use_pygments = True
|
||||||
sticky_by_default: bool = False
|
sticky_by_default = True
|
||||||
enable_hidden_frames: bool = False
|
enable_hidden_frames = False
|
||||||
|
|
||||||
# much thanks @mdmintz for the hot tip!
|
|
||||||
# fixes line spacing issue when resizing terminal B)
|
|
||||||
truncate_long_lines: bool = False
|
|
||||||
|
|
||||||
|
|
||||||
class MultiActorPdb(pdbp.Pdb):
|
class MultiActorPdb(pdbp.Pdb):
|
||||||
|
@ -754,8 +750,8 @@ def shield_sigint_handler(
|
||||||
|
|
||||||
|
|
||||||
def _set_trace(
|
def _set_trace(
|
||||||
actor: tractor.Actor | None = None,
|
actor: Optional[tractor.Actor] = None,
|
||||||
pdb: MultiActorPdb | None = None,
|
pdb: Optional[MultiActorPdb] = None,
|
||||||
):
|
):
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
actor = actor or tractor.current_actor()
|
actor = actor or tractor.current_actor()
|
||||||
|
@ -765,11 +761,7 @@ def _set_trace(
|
||||||
if frame:
|
if frame:
|
||||||
frame = frame.f_back # type: ignore
|
frame = frame.f_back # type: ignore
|
||||||
|
|
||||||
if (
|
if frame and pdb and actor is not None:
|
||||||
frame
|
|
||||||
and pdb
|
|
||||||
and actor is not None
|
|
||||||
):
|
|
||||||
log.pdb(f"\nAttaching pdb to actor: {actor.uid}\n")
|
log.pdb(f"\nAttaching pdb to actor: {actor.uid}\n")
|
||||||
# no f!#$&* idea, but when we're in async land
|
# no f!#$&* idea, but when we're in async land
|
||||||
# we need 2x frames up?
|
# we need 2x frames up?
|
||||||
|
@ -778,8 +770,7 @@ def _set_trace(
|
||||||
else:
|
else:
|
||||||
pdb, undo_sigint = mk_mpdb()
|
pdb, undo_sigint = mk_mpdb()
|
||||||
|
|
||||||
# we entered the global ``breakpoint()`` built-in from sync
|
# we entered the global ``breakpoint()`` built-in from sync code?
|
||||||
# code?
|
|
||||||
Lock.local_task_in_debug = 'sync'
|
Lock.local_task_in_debug = 'sync'
|
||||||
|
|
||||||
pdb.set_trace(frame=frame)
|
pdb.set_trace(frame=frame)
|
||||||
|
|
|
@ -22,9 +22,8 @@ from contextlib import asynccontextmanager
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import importlib
|
import importlib
|
||||||
import logging
|
import logging
|
||||||
import signal
|
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
import typing
|
import typing
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
@ -85,10 +84,8 @@ async def open_root_actor(
|
||||||
|
|
||||||
'''
|
'''
|
||||||
# Override the global debugger hook to make it play nice with
|
# Override the global debugger hook to make it play nice with
|
||||||
# ``trio``, see much discussion in:
|
# ``trio``, see:
|
||||||
# https://github.com/python-trio/trio/issues/1155#issuecomment-742964018
|
# https://github.com/python-trio/trio/issues/1155#issuecomment-742964018
|
||||||
builtin_bp_handler = sys.breakpointhook
|
|
||||||
orig_bp_path: str | None = os.environ.get('PYTHONBREAKPOINT', None)
|
|
||||||
os.environ['PYTHONBREAKPOINT'] = 'tractor._debug._set_trace'
|
os.environ['PYTHONBREAKPOINT'] = 'tractor._debug._set_trace'
|
||||||
|
|
||||||
# attempt to retreive ``trio``'s sigint handler and stash it
|
# attempt to retreive ``trio``'s sigint handler and stash it
|
||||||
|
@ -259,15 +256,6 @@ async def open_root_actor(
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
_state._current_actor = None
|
_state._current_actor = None
|
||||||
|
|
||||||
# restore breakpoint hook state
|
|
||||||
sys.breakpointhook = builtin_bp_handler
|
|
||||||
if orig_bp_path is not None:
|
|
||||||
os.environ['PYTHONBREAKPOINT'] = orig_bp_path
|
|
||||||
else:
|
|
||||||
# clear env back to having no entry
|
|
||||||
os.environ.pop('PYTHONBREAKPOINT')
|
|
||||||
|
|
||||||
logger.runtime("Root actor terminated")
|
logger.runtime("Root actor terminated")
|
||||||
|
|
||||||
|
|
||||||
|
@ -303,7 +291,7 @@ def run_daemon(
|
||||||
async def _main():
|
async def _main():
|
||||||
|
|
||||||
async with open_root_actor(
|
async with open_root_actor(
|
||||||
registry_addr=registry_addr,
|
arbiter_addr=registry_addr,
|
||||||
name=name,
|
name=name,
|
||||||
start_method=start_method,
|
start_method=start_method,
|
||||||
debug_mode=debug_mode,
|
debug_mode=debug_mode,
|
||||||
|
|
|
@ -998,7 +998,7 @@ class Actor:
|
||||||
log.warning(
|
log.warning(
|
||||||
f"Failed to connect to parent @ {parent_addr},"
|
f"Failed to connect to parent @ {parent_addr},"
|
||||||
" closing server")
|
" closing server")
|
||||||
await self.cancel(requesting_uid=self.uid)
|
await self.cancel()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
async def _serve_forever(
|
async def _serve_forever(
|
||||||
|
|
Loading…
Reference in New Issue