Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack spew when quitting via the debugger #1155

Open
smurfix opened this issue Jul 25, 2019 · 6 comments
Open

Stack spew when quitting via the debugger #1155

smurfix opened this issue Jul 25, 2019 · 6 comments

Comments

@smurfix
Copy link
Contributor

smurfix commented Jul 25, 2019

Can we do better than this?

smurf@dev:~/src/distkv$ ./kv server -l  0.dkv $(hostname)
> /src/distkv/distkv/server.py(2155)load()
-> m = UpdateEvent.deserialize(
(Pdb) c
Running.
^C
Program interrupted. (Use 'cont' to resume).
> /usr/lib/python3/dist-packages/trio/_core/_io_epoll.py(70)handle_io()
-> for fd, flags in events:
(Pdb) q
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1430, in run
    run_impl(runner, async_fn, args)
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1494, in run_impl
    runner.io_manager.handle_io(timeout)
  File "/usr/lib/python3/dist-packages/trio/_core/_io_epoll.py", line 70, in handle_io
    for fd, flags in events:
  File "/usr/lib/python3/dist-packages/trio/_core/_io_epoll.py", line 70, in handle_io
    for fd, flags in events:
  File "/usr/lib/python3.7/bdb.py", line 88, in trace_dispatch
    return self.dispatch_line(frame)
  File "/usr/lib/python3.7/bdb.py", line 113, in dispatch_line
    if self.quitting: raise BdbQuit
bdb.BdbQuit

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "./kv", line 18, in <module>
    cmd()
  File "./distkv/command.py", line 84, in cmd
    main(standalone_mode=False)
  File "/usr/lib/python3/dist-packages/trio_click/core.py", line 799, in __call__
    return anyio.run(self._main, main, args, kwargs, backend=_anyio_backend)
  File "/usr/lib/python3/dist-packages/anyio/__init__.py", line 66, in run
    return asynclib.run(func, *args, **backend_options)  # type: ignore
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1430, in run
    run_impl(runner, async_fn, args)
trio.TrioInternalError: internal error in trio - please file a bug!
Exception ignored in: <function Nursery.__del__ at 0x7fd9cb9351e0>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 638, in __del__
AssertionError: 
Exception ignored in: <function Nursery.__del__ at 0x7fd9cb9351e0>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 638, in __del__
AssertionError: 
Exception ignored in: <coroutine object Actor.spawn.<locals>._run at 0x7fd9ca9f7b48>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/actor.py", line 430, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <coroutine object BaseCommand._main at 0x7fd9cb9148c8>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/trio_click/core.py", line 802, in _main
  File "/usr/lib/python3/dist-packages/trio_click/core.py", line 748, in main
  File "/usr/lib/python3/dist-packages/trio_click/core.py", line 1175, in invoke
  File "/usr/lib/python3/dist-packages/trio_click/core.py", line 994, in invoke
  File "/usr/lib/python3/dist-packages/trio_click/core.py", line 588, in invoke
  File "./distkv/commands/server.py", line 124, in cli
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 121, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 493, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 583, in _nested_child_finished
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 563, in _add_exc
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 340, in cancel
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 742, in _attempt_delivery_of_any_pending_cancel
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 724, in _attempt_abort
  File "/usr/lib/python3/dist-packages/trio/_core/_io_epoll.py", line 114, in abort
KeyError: 8
Exception ignored in: <function Nursery.__del__ at 0x7fd9cb9351e0>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 638, in __del__
AssertionError: 
Exception ignored in: <coroutine object Serf.spawn.<locals>._run at 0x7fd9ca9f71c8>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/client.py", line 115, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <function Nursery.__del__ at 0x7fd9cb9351e0>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 638, in __del__
AssertionError: 
Exception ignored in: <coroutine object _Server._accept at 0x7fd9ca9a4f48>
Traceback (most recent call last):
  File "./distkv/util.py", line 430, in _accept
  File "/usr/lib/python3/dist-packages/anyio/__init__.py", line 137, in open_cancel_scope
  File "/usr/lib/python3/dist-packages/anyio/__init__.py", line 85, in _get_asynclib
  File "/usr/lib/python3/dist-packages/sniffio/_impl.py", line 81, in current_async_library
sniffio._impl.AsyncLibraryNotFoundError: unknown async library, or not in async context
Exception ignored in: <coroutine object _Server._accept at 0x7fd9ca9bf048>
Traceback (most recent call last):
  File "./distkv/util.py", line 430, in _accept
  File "/usr/lib/python3/dist-packages/anyio/__init__.py", line 137, in open_cancel_scope
  File "/usr/lib/python3/dist-packages/anyio/__init__.py", line 85, in _get_asynclib
  File "/usr/lib/python3/dist-packages/sniffio/_impl.py", line 81, in current_async_library
sniffio._impl.AsyncLibraryNotFoundError: unknown async library, or not in async context
Exception ignored in: <coroutine object SerfConnection._reader at 0x7fd9ca9f7248>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/connection.py", line 309, in _reader
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <coroutine object Actor.spawn.<locals>._run at 0x7fd9ca99c6c8>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/actor.py", line 430, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <function Nursery.__del__ at 0x7fd9cb9351e0>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 638, in __del__
AssertionError: 
Exception ignored in: <coroutine object Actor.spawn.<locals>._run at 0x7fd9ca9a42c8>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/actor.py", line 430, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <coroutine object Serf.spawn.<locals>._run at 0x7fd9ca9f7cc8>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/client.py", line 115, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <coroutine object Serf.spawn.<locals>._run at 0x7fd9ca9f72c8>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/client.py", line 115, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <coroutine object Serf.spawn.<locals>._run at 0x7fd9ca9f7348>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/client.py", line 115, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <coroutine object Serf.spawn.<locals>._run at 0x7fd9ca99c7c8>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/client.py", line 115, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <coroutine object Actor.spawn.<locals>._run at 0x7fd9ca9a4348>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/actor.py", line 430, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <coroutine object Actor.spawn.<locals>._run at 0x7fd9ca9f7ac8>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/actor.py", line 430, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <coroutine object Actor.spawn.<locals>._run at 0x7fd9ca9a4748>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/actor.py", line 430, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <coroutine object Serf.spawn.<locals>._run at 0x7fd9ca9f70c8>
Traceback (most recent call last):
  File "../asyncserf/asyncserf/client.py", line 115, in _run
  File "/usr/lib/python3/dist-packages/anyio/_backends/_trio.py", line 49, in __aexit__
  File "/usr/lib/python3/dist-packages/trio/_core/_ki.py", line 165, in wrapper
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 199, in __exit__
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 367, in _close
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1645, in current_task
RuntimeError: must be called from async context
Exception ignored in: <function Nursery.__del__ at 0x7fd9cb9351e0>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 638, in __del__
AssertionError: 
Exception ignored in: <coroutine object Server._accept_clients at 0x7fd9ca9f7148>
RuntimeError: coroutine ignored GeneratorExit
@njsmith
Copy link
Member

njsmith commented Jul 26, 2019

Ick, that's certainly an unpleasant pile of junk.

It looks like what's happening is:

  • pdb is injecting a BdbQuit exception into some arbitrary point inside Trio's internals
  • Trio sees that some unexpected exception happened inside its internals, converts that into a TrioInternalError, and lets the run loop crash
  • In the process, it abandons all the running tasks, and eventually the coroutine objects get garbage collected
  • The garbage collector re-starts the tasks with a GeneratorExit, causing various mayhem as they attempt to unwind, but now they're running in this weird GC context instead of the regular Trio context

What do we want to happen here? I guess ideally, pdb would be smart enough to work at the "Trio level", treating the Trio internals as opaque and treating tasks as first-class objects, and injecting BdbQuit into a task, similar to what we do with KeyboardInterrupt. But pdb isn't this clever, and anyway, sometimes you do want to use pdb to debug Trio's internals. So I guess we need to figure out what users expect if they inject a BdbQuit into Trio's internals.

I don't think we can do a clean unwind like we would for a user exception or KeyboardInterrupt – depending on where the exception happens, it might have left the scheduler with inconsistent state. And generally if you hit q in pdb, you want to just kill the program. So I guess we just want to make Trio's last-ditch exception handling slightly smarter, to crash out but with less random spew.

A simple change would be to special-case BdbQuit, and let it escape normally, instead of wrapping it in TrioInternalError. Then pdb will catch it instead of printing a traceback. That fixes the first few lines of the giant paste above.

The other sources of spew I see are:

  • Nursery.__del__. This is just an assertion to try to notice if we had some weird bug, or if someone is misusing nurseries. I don't think we've ever seen it actually catch anything on its own; it's always just extra clutter on some explosion like this. We could probably drop it.

  • The main task was blocked in nursery.__aexit__, and when GeneratorExit was injected it interpreted this similarly to a crashed child, and tried to find and cancel the other children. Then this crashed because of the weird state everything was in.

  • Lots of cancel scopes getting grumpy about you exiting them from outside Trio context.

  • Some anyio code getting grumpy about being called outside Trio (or any other async library) context.

My first thought was that maybe we could do something to manually tear down all these tasks before the GC has a chance to do it, so that it still happens in Trio context. (This is similar to what we need to do for async generators – see #265 and especially #265 (comment).) However, I don't think this will work. The main thing that's failing is calls to current_task(), and we can't make that do anything meaningful if we don't have a working scheduler, plus even if it succeeded then the next thing the code would do would> #265 (comment)

be to try to manipulate other data structures that are also in inconsistent states. (Like what happens to the nursery cleanup code.)

Maybe we could add some specific hacks to Nursery.__aexit__ and CancelScope._close to detect this case and exit more silently? Possible approaches:

  • Both of these methods have access to the exception, so they could potentially treat GeneratorExit specially. (Are there any other cases where it can be raised? I think it can happen for async generators too, but that would mean someone yielded inside a nursery/cancel-scope, and that's always wrong too.)

  • Or they could notice when they're called from outside Trio context and do something special. Detect the case and print a more useful warning, plus track whether we've already issued such a warning so we can suppress duplicates?

  • Or Trio's last-ditch cleanup code could manually call close on all coroutine objects, to trigger the GeneratorExit, and let it crash like it is now – but then because we're calling it instead of the GC, we can catch the resulting crashes and print something more useful. (Maybe a different thing for BdbQuit than for other errors, even.) Actually in general this might be nice... right now when you get a TrioInternalError it always comes with a giant useless spew like this. Probably it would be more useful to first dump a nice stack trace (Provide a helper to dump the task tree / stack tree #927) and then discard any exceptions that happen during emergency teardown.

@goodboy
Copy link
Member

goodboy commented Dec 11, 2020

@njsmith so here's another fun one:

If you enter a breakpoint() and then continue, ctrl-c handling entirely breaks from that point forward in trio.
More fun is that it's entirely cause by the stdlib's default Pdb instance settings, namely mangling of sigint handling 😢

Here's some example code with demonstrates this failure:

import pdb

import trio

async def trace():

    breakpoint()

    while True:
        await trio.sleep(0.1)


async def spawn_debuggers():
    async with trio.open_nursery() as n:
        n.start_soon(trace)
        n.start_soon(trio.sleep_forever)


trio.run(spawn_debuggers)

After running the continue command (aka c) from the repl ctrl-c handling is now broken and further ctrl-c from the user just re-enters the repl.

@smurfix using quit (aka q) seems to work here though (even if you run use it after hitting the KBI-to-cancel-is-disabled state) so I'm wondering what kind of situation you were in 🤔

Proposal

For the KBI borking problem mentioned, I propose we just write our own breakpoint() hook and set both Pdb.nosigint (such that the default handler isn't reverted) and Pdb.allow_kbint to True such that we get standard trio cancellation behavior.

I guess you could argue the "halting sync code wherever it is currently running" can sometimes be useful, but I'm just not sure that's so compatible with trio usage?

I personally found the whole situation extremely difficult to grok once you involve a foreign host loop in guest mode and your code gets stuck blocking forever in that loop after having used the debugger 🤯

@goodboy
Copy link
Member

goodboy commented Dec 11, 2020

Oh wow wait ma bad @smurfix, just realized I almost always have pdb++ installed.

With the stdlib's debugger it's what you posted:

3.9)  >>> python trio_pdb.py 
> /home/goodboy/repos/tractor/trio_pdb.py(10)trace()
-> await trio.sleep(0.1)
(Pdb) c
^C
Program interrupted. (Use 'cont' to resume).
--Return--
> /home/goodboy/repos/trio/trio/_core/_io_epoll.py(229)get_events()->[(6, 1)]
-> return self._epoll.poll(timeout, max_events)
(Pdb) q
Traceback (most recent call last):
  File "/home/goodboy/repos/tractor/trio_pdb.py", line 19, in <module>
    trio.run(spawn_debuggers)
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 1931, in run
    next_send = runner.io_manager.get_events(timeout)
  File "/home/goodboy/repos/trio/trio/_core/_io_epoll.py", line 229, in get_events
    return self._epoll.poll(timeout, max_events)
  File "/usr/lib/python3.9/bdb.py", line 92, in trace_dispatch
    return self.dispatch_return(frame, arg)
  File "/usr/lib/python3.9/bdb.py", line 154, in dispatch_return
    if self.quitting: raise BdbQuit
bdb.BdbQuit
/home/goodboy/repos/trio/trio/_core/_run.py:2226: RuntimeWarning: Trio guest run got abandoned without properly finishing... weird stuff might happen
  warnings.warn(
Exception ignored in: <coroutine object Runner.init at 0x7f342f0ba9c0>
Traceback (most recent call last):
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 1608, in init
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 802, in __aexit__
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 914, in _nested_child_finished
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 896, in _add_exc
  File "/home/goodboy/repos/trio/trio/_core/_ki.py", line 159, in wrapper
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 681, in cancel
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 357, in recalculate
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 1169, in _attempt_delivery_of_any_pending_cancel
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 1151, in _attempt_abort
  File "/home/goodboy/repos/trio/trio/_core/_io_epoll.py", line 292, in abort
  File "/home/goodboy/repos/trio/trio/_core/_io_epoll.py", line 261, in _update_registrations
ValueError: I/O operation on closed epoll object
Exception ignored in: <function Nursery.__del__ at 0x7f342f67e4c0>
Traceback (most recent call last):
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 1050, in __del__
AssertionError:
Exception ignored in: <function Nursery.__del__ at 0x7f342f67e4c0>
Traceback (most recent call last):
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 1050, in __del__
AssertionError:
Exception ignored in: <function Nursery.__del__ at 0x7f342f67e4c0>
Traceback (most recent call last):
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 1050, in __del__
AssertionError:
Exception ignored in: <coroutine object trace at 0x7f342f0bac40>
Traceback (most recent call last):
  File "/home/goodboy/repos/tractor/trio_pdb.py", line 10, in trace
  File "/home/goodboy/repos/trio/trio/_timeouts.py", line 75, in sleep
  File "/home/goodboy/repos/trio/trio/_timeouts.py", line 56, in sleep_until
  File "/home/goodboy/repos/trio/trio/_core/_ki.py", line 159, in wrapper
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 539, in __exit__
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 476, in _close
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 2276, in current_task
RuntimeError: must be called from async context

Heh, I guess also we get a new error msg since guest mode was introduced.
Interestingly though it's still due to the core issue I reported with SIGINT handling I'm pretty sure.

If you just enter q on the first prompt we're all good:

> /home/goodboy/repos/tractor/trio_pdb.py(10)trace()
-> await trio.sleep(0.1)
(Pdb) q
Traceback (most recent call last):
  File "/home/goodboy/repos/tractor/trio_pdb.py", line 19, in <module>
    trio.run(spawn_debuggers)
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 1928, in run
    timeout = gen.send(next_send)
  File "/home/goodboy/repos/tractor/trio_pdb.py", line 16, in spawn_debuggers
    n.start_soon(trio.sleep_forever)
  File "/home/goodboy/repos/trio/trio/_core/_run.py", line 815, in __aexit__
    raise combined_error_from_nursery
  File "/home/goodboy/repos/tractor/trio_pdb.py", line 10, in trace
    await trio.sleep(0.1)
  File "/home/goodboy/repos/tractor/trio_pdb.py", line 10, in trace
    await trio.sleep(0.1)
  File "/usr/lib/python3.9/bdb.py", line 88, in trace_dispatch
    return self.dispatch_line(frame)
  File "/usr/lib/python3.9/bdb.py", line 113, in dispatch_line
    if self.quitting: raise BdbQuit
bdb.BdbQuit

So I think we might get a few birds here by changing these flags.

@goodboy
Copy link
Member

goodboy commented Dec 11, 2020

Oh, and just so that I'm not talking lots of air, I did fix this in tractor by tweaking these settings, and in that case it's working in subprocesses as well so I'm pretty sure it's a sound fix 😉

goodboy added a commit to goodboy/tractor that referenced this issue Dec 11, 2020
Turns out this is a lower level issue in terms of the stdlib's default
`pdb.Pdb` settings and how they conflict with `trio`s cancellation and
KBI handling. The details are hashed out more thoroughly in
python-trio/trio#1155. Maybe we can get a fix in trio so things are
solved under our feet :)
@mikenerone
Copy link
Member

Chiming in per chat request: pudb (a full-screen terminal debugger) seems unaffected by this. When it's activated via breakpoint while running under trio, it issues this warning:

UserWarning: A non-default handler for signal 2 is already installed (<function KIManager.install.<locals>.handler at 0x10bc6b670>). Skipping pudb interrupt support.

True to its word, once you continue execution from the debugger, hitting CTRL-C causes an exit with a completely normal KeyboardInterrupt stack trace.

@goodboy
Copy link
Member

goodboy commented Dec 11, 2020

@mikeengland perfect, yes this is the default behavior I would expect.

I think this adds fuel for this change I've got in mind.

goodboy added a commit to goodboy/tractor that referenced this issue Feb 21, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Feb 21, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Feb 22, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Feb 24, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Feb 25, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Mar 1, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Apr 27, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Apr 28, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Apr 28, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Apr 29, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue May 6, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue May 6, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue May 10, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue May 12, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue May 31, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue May 31, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Jun 11, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Jun 11, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Jun 24, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Aug 10, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Aug 10, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Aug 24, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Aug 24, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 1, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 1, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 2, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 3, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 3, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 3, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 8, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 8, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 8, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 18, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 18, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 18, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 18, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 18, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Sep 18, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Oct 8, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Oct 8, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Oct 8, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Oct 23, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Oct 23, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Oct 23, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Oct 28, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Oct 28, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
goodboy added a commit to goodboy/tractor that referenced this issue Oct 28, 2021
Override `breakpoint()` for sync code making it work
properly with `trio` as per:

python-trio/trio#1155 (comment)

Relates to #193
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants