Skip to content

Remote PDB can't interrupt an infinite loop in an evaluated command #132975

Closed
@godlygeek

Description

@godlygeek

Bug report

Bug description:

As @gaogaotiantian pointed out in #132451 (comment) PDB's new remote attaching feature can enter an uninterruptible infinite loop if you type while True: pass at a PDB prompt. We're able to interrupt the script itself, when you 'cont'inue past a breakpoint, but aren't able to interrupt a statement evaluated interactively at a PDB prompt.

I have a few different ideas for how this could be fixed, though they all have different tradeoffs.

Options:

  1. the client can send a SIGINT signal to the remote.
    • Pro: it can interrupt IO, as long as PyErr_CheckSignals() is being called by the main thread
    • Con: it will not work on Windows
    • Con: it will kill the process if the SIGINT handler has been unset (and PDB does mess with the signal handler - I'm not sure this is just a theoretical problem)
  1. we can raise a KeyboardInterrupt from an injected script
    • Pro: It will work on Windows
    • Con: We need to change sys.remote_exec() to allow KeyboardInterrupt to escape
    • Pro: A looping injected script can be killed now, though!
    • Con: It cannot interrupt IO
    • Con: The KeyboardInterrupt will get raised even in places where signals were blocked, potentially leading to a crash where something that should never get an exception got one
  1. we can make PDB stop if set_trace() is called while it's evaluating a user-supplied statement
    • Pro: it will work on Windows
    • Con: It cannot interrupt IO
    • Con: it will lead to recursion of PDB's trace function if the script is interrupted, and I don't know how well PDB will handle that
  1. the PDB server can start a thread that listens to a socket and calls signal.raise_signal(signal.SIGINT) every time it gets a message on the socket
    • Pro: it can interrupt IO in the same cases as 1 can
    • Pro: it works in "true remote" scenarios where the client and server are on different hosts (which isn't currently a feature, but would be a nice future feature)
    • Pro: it works on Windows
    • Con: more complexity, more failure modes

I'm currently leaning towards (4) - it's the most complete fix and works on the most platforms and the most scenarios (interrupting both CPU-bound and IO-bound stuff). I plan to prototype this soon.

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.14bugs and security fixesstdlibPython modules in the Lib dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions