Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
5225333
Allow pdb to attach to a running process
godlygeek Apr 12, 2025
78a3085
Remove 2 unused _RemotePdb instance attributes
godlygeek Apr 15, 2025
90e0a81
Reduce duplication for 'debug' command
godlygeek Apr 15, 2025
e44a670
End commands entry on 'end' and ^C and ^D
godlygeek Apr 15, 2025
e837246
Set the frame for remote pdb to stop in explicitly
godlygeek Apr 15, 2025
27efa97
Fix an unbound local in an error message
godlygeek Apr 15, 2025
557a725
Clean up remote PDB detaching
godlygeek Apr 15, 2025
7f7584a
Allow ctrl-c to interrupt a running process
godlygeek Apr 17, 2025
5666ffb
Automatically detach if the client dies unexpectedly
godlygeek Apr 17, 2025
325f166
Clear _last_pdb_instance on detach
godlygeek Apr 17, 2025
72830e2
Refuse to attach if another PDB instance is installed
godlygeek Apr 17, 2025
27c6780
Handle the confirmation prompt issued by 'clear'
godlygeek Apr 18, 2025
baaf28a
Make message and error handle non-string args
godlygeek Apr 18, 2025
e61cc31
Add some basic tests
pablogsal Apr 18, 2025
5d59ce1
Don't use deprecated method
pablogsal Apr 18, 2025
09adb2b
Try to prevent a PermissionError on Windows
godlygeek Apr 18, 2025
600aa05
Address review comments
godlygeek Apr 20, 2025
0601f10
Add protocol versioning and support -c commands
godlygeek Apr 20, 2025
5a1755b
Fix tests to match new _connect signature for protocol versioning/com…
godlygeek Apr 21, 2025
f184e4e
Add some comments describing our protocol
godlygeek Apr 21, 2025
82b71f8
Use the 'commands' state for '(com)' prompts
godlygeek Apr 22, 2025
3986c17
Remove choices parameter from _prompt_for_confirmation
godlygeek Apr 22, 2025
2e69667
Rename _RemotePdb to _PdbServer
godlygeek Apr 22, 2025
55adbcc
Avoid fallthrough in signal handling
godlygeek Apr 22, 2025
0bda5c2
Fix handling of a SystemExit raised in normal pdb mode
godlygeek Apr 22, 2025
5e93247
Address nit
godlygeek Apr 22, 2025
f799e83
Use textwrap.dedent for test readability
godlygeek Apr 22, 2025
46fb219
Drop dataclasses dependency
godlygeek Apr 22, 2025
1ec9475
Combine the two blocks for handling -p PID into one
godlygeek Apr 22, 2025
662c7eb
Add a news entry
godlygeek Apr 22, 2025
ac36d7d
Skip remote PDB integration test on WASI
godlygeek Apr 22, 2025
f06d9c2
Two small things missed in the previous fixes
godlygeek Apr 22, 2025
715af27
Remove call to set_step in interrupt handler
godlygeek Apr 22, 2025
c654fdf
More tests
pablogsal Apr 23, 2025
205bc55
More tests
pablogsal Apr 23, 2025
bbe784b
More tests
pablogsal Apr 23, 2025
30cb537
Add what's new entry
pablogsal Apr 23, 2025
659556f
use dedent
pablogsal Apr 23, 2025
6c2d970
Add synchronization to test_keyboard_interrupt
godlygeek Apr 24, 2025
100be44
Stop sending a "signal" message in test_keyboard_interrupt"
godlygeek Apr 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
End commands entry on 'end' and ^C and ^D
  • Loading branch information
godlygeek committed Apr 15, 2025
commit e44a670b0c7a62642777197cc8402a71ca87114e
7 changes: 5 additions & 2 deletions Lib/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -2706,6 +2706,7 @@ def do_commands(self, arg):
]
# fmt: on

end_cmds += ["end"] # pseudo-command
self._send(commands_entry={"bpnum": bnum, "terminators": end_cmds})
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to send these end commands back and forth? They are constants. Also end is a very important one (arguably the most important one as it's in the example).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're constants, but they're not necessarily the same constants for the client and the server, since they can be running different versions of Python.

If the attaching client is running 3.14.9 and the remote PDB server is running 3.14.0, it's possible that the client will think that some command should terminate the command list, and send a command list to the server that the server thinks is incomplete because it doesn't recognize that terminator. If that happened, we'd be out of sync - the server would still be waiting for more lines, and the client would think that it's done sending lines.

That said, perhaps I'm being overly defensive, and we shouldn't expect any new command to ever be added after 3.X final. But the risk of getting it wrong is leaving you with a broken debugger session that might only be able to be fixed by killing the client.

Another possible option is to be defensive in the:

        for line in commands:
            if self.handle_command_def(line):
                break

loop below. We could say that loop must break, and that if it doesn't, it can only mean that we got a list that was unterminated, and so we should roll back to the old set of commands. If you prefer that over sending list of early-command-terminators back over the wire, I'm fine with that.

That'd just be something like (pseudocode):

        saved = old_commands_for_breakpoint(bnum)
        for line in commands:
            if self.handle_command_def(line):
                break
        else:
            self.error("Incomplete command list!")
            set_commands_for_breakpoint(bnum, saved)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the server would still be waiting for more lines, and the client would think that it's done sending lines.

That won't happen. When the client sent the commands as a list, the server will just finish the list and consider it done for the commands. Nothing worse would happen.

Also, I don't expect the list of resuming commands to change. And as discussed elsewhere, I don't think we should support cross version debugging.

I just tested it and CTRL+D does not work either (to terminate the commands).

Copy link
Copy Markdown
Contributor Author

@godlygeek godlygeek Apr 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That won't happen. When the client sent the commands as a list, the server will just finish the list and consider it done for the commands. Nothing worse would happen.

Ah, you're right - I misremembered and thought that _RemotePdb sets self.commands_defining = True, but it doesn't (it used to in one of my earlier iterations).

OK, in that case, the only reason I can think of to send the list of resuming commands from the remote to the client is aliases. Currently I'm not handling that, and I'm just hardcoding, but in regular PDB you can:

(Pdb) alias blah cont
(Pdb) import functools
(Pdb) b functools.cache
Breakpoint 1 at /opt/bb/lib/python3.13/functools.py:676
(Pdb) commands
(com) p "hello from breakpoint"
(com) blah
(Pdb)

Note that blah ended the command list. The only way we can support that for remote PDB is to send the list of resuming commands from the server to the client. But, I also don't care much if we support that. As you say, if we don't, the only impact is that the user needs to a) use the regular command instead of the alias, or b) add an end command.

That seems fine to me. I think that having the resuming commands end the command list is a weird feature anyway, but I was aiming for feature parity.

So: if you care about aliases for resuming commands ending the commands list, I'll keep this code and update it to also send the list of aliases that expand to one of the commands in the list.

If you don't care about aliases for resuming commands ending the command list, I'm happy to hardcode the list client-side instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tested it and CTRL+D does not work either (to terminate the commands).

Not for regular PDB either, so that's fine.

But ctrl-c just kills the whole remote pdb client, that's wrong.

Also end is a very important one

lol oops, that's what I get for focusing on edge cases 🤣

Fixed 'end' and ctrl-c in e44a670

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the only "correct" way to do this is to send the commands to the server one by one - you'll never get the correct result with client parsing. For example, x = 1;;continue should end the command prompt, and the current client does not do that. Unless you parse everything exactly as the server does, you won't get the same result.

For your blah example - the current code does not handle it, and it would be complicated to make it work properly. If we want to make it right, we need to simulate the send/receive line by line.

The worse case in the current implementation is that the user needs to end the command with an end - that's not too bad. We can do it for now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, x = 1;;continue should end the command prompt, and the current client does not do that.

Oof, yeah. I didn't think about ;;

If we want to make it right, we need to simulate the send/receive line by line.

I can do that. It wouldn't be too tough, and it would wind up looking a lot like interact - set a flag for the "mode", and make it be possible for the client to return to command mode (on ctrl-c or ctrl-d) or for the server to (when the command list is terminated).

I understand how to do this, and it wouldn't be difficult, but it would be almost exactly as complex as interact, for better or worse.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 600aa05

return

Expand Down Expand Up @@ -2875,8 +2876,10 @@ def prompt_for_breakpoint_command_list(self, prompt):
cmd = self.pdb_instance.parseline(line)[0]
if cmd in self.command_list_terminators:
break
except EOFError:
return
except (KeyboardInterrupt, EOFError):
print(flush=True)
print("command definition aborted, old commands restored")
break
finally:
self.commands_mode = False

Expand Down
Loading