diff --git a/tractor/_debug.py b/tractor/_debug.py index 5d3626be4..e5da9a53c 100644 --- a/tractor/_debug.py +++ b/tractor/_debug.py @@ -3,7 +3,7 @@ """ import sys from functools import partial -from typing import Awaitable, Tuple +from typing import Awaitable, Tuple, Optional, Callable from async_generator import aclosing import tractor @@ -27,18 +27,25 @@ __all__ = ['breakpoint', 'post_mortem'] -# TODO: is there some way to determine this programatically? -_pdb_exit_patterns = tuple( - str.encode(patt + "\n") for patt in ('c', 'cont', 'continue', 'q', 'quit') -) +# placeholder for function to set a ``trio.Event`` +_pdb_release_hook: Optional[Callable] = None -_pdb_release_hook = None +class TractorConfig(pdbpp.DefaultConfig): + """Custom ``pdbpp`` goodness. + """ + sticky_by_default = True + + def teardown(self, _pdb): + _pdb_release_hook(_pdb) class PdbwTeardown(pdbpp.Pdb): """Add teardown hooks to the regular ``pdbpp.Pdb``. """ + # override the pdbpp config with our coolio one + DefaultConfig = TractorConfig + # TODO: figure out how to dissallow recursive .set_trace() entry # since that'll cause deadlock for us. def set_continue(self): @@ -50,22 +57,15 @@ def set_quit(self): self.config.teardown(self) -class TractorConfig(pdbpp.DefaultConfig): - """Custom ``pdbpp`` goodness. - """ - sticky_by_default = True - - def teardown(self, _pdb): - _pdb_release_hook(_pdb) - - -# override the pdbpp config with our coolio one -pdbpp.Pdb.DefaultConfig = TractorConfig - - # TODO: will be needed whenever we get to true remote debugging. # XXX see https://github.com/goodboy/tractor/issues/130 +# # TODO: is there some way to determine this programatically? +# _pdb_exit_patterns = tuple( +# str.encode(patt + "\n") for patt in ( +# 'c', 'cont', 'continue', 'q', 'quit') +# ) + # def subactoruid2proc( # actor: 'Actor', # noqa # uid: Tuple[str, str] @@ -170,17 +170,16 @@ def unlock(_pdb): _pdb_release_hook = unlock async def _bp(): - # this must be awaited by caller - await actor._root_nursery.start( - wait_for_parent_stdin_hijack - ) + # this **must** be awaited by the caller and is done using the + # root nursery so that the debugger can continue to run without + # being restricted by the scope of a new task nursery. + await actor._root_nursery.start(wait_for_parent_stdin_hijack) - # block here one frame up where ``breakpoint()`` - # was awaited and begin handling stdin + # block here one (at the appropriate frame *up* where + # ``breakpoint()`` was awaited and begin handling stdio debug_func(actor) - # return wait_for_parent_stdin_hijack() - return _bp() + return _bp() # user code **must** await this! def _set_trace(actor):