Skip to content

Commit 0601f10

Browse files
committed
Add protocol versioning and support -c commands
1 parent 600aa05 commit 0601f10

File tree

1 file changed

+38
-5
lines changed

1 file changed

+38
-5
lines changed

Lib/pdb.py

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2526,6 +2526,19 @@ def __init__(self, sockfile, owns_sockfile=True, **kwargs):
25262526
self._write_failed = False
25272527
super().__init__(**kwargs)
25282528

2529+
@staticmethod
2530+
def protocol_version():
2531+
# By default, assume a client and server are compatible if they run
2532+
# the same Python major.minor version. We'll try to keep backwards
2533+
# compatibility between patch versions of a minor version if possible.
2534+
# If we do need to change the protocol in a patch version, we'll change
2535+
# `revision` to the patch version where the protocol changed.
2536+
# We can ignore compatibility for pre-release versions; sys.remote_exec
2537+
# can't attach to a pre-release version except from that same version.
2538+
v = sys.version_info
2539+
revision = 0
2540+
return int(f"{v.major:02X}{v.minor:02X}{revision:02X}F0", 16)
2541+
25292542
def _send(self, **kwargs) -> None:
25302543
json_payload = json.dumps(kwargs)
25312544
try:
@@ -2926,7 +2939,7 @@ def complete(self, text, state):
29262939
return None
29272940

29282941

2929-
def _connect(host, port, frame):
2942+
def _connect(host, port, frame, commands, version):
29302943
with closing(socket.create_connection((host, port))) as conn:
29312944
sockfile = conn.makefile("rwb")
29322945

@@ -2935,19 +2948,39 @@ def _connect(host, port, frame):
29352948

29362949
if Pdb._last_pdb_instance is not None:
29372950
remote_pdb.error("Another PDB instance is already attached.")
2951+
elif version != remote_pdb.protocol_version():
2952+
target_ver = f"0x{remote_pdb.protocol_version():08X}"
2953+
attach_ver = f"0x{version:08X}"
2954+
remote_pdb.error(
2955+
f"The target process is running a Python version that is"
2956+
f" incompatible with this PDB module."
2957+
f"\nTarget process pdb protocol version: {target_ver}"
2958+
f"\nLocal pdb module's protocol version: {attach_ver}"
2959+
)
29382960
else:
2961+
remote_pdb.rcLines.extend(commands.splitlines())
29392962
remote_pdb.set_trace(frame=frame)
29402963

29412964

2942-
def attach(pid):
2965+
def attach(pid, commands=()):
29432966
"""Attach to a running process with the given PID."""
29442967
with closing(socket.create_server(("localhost", 0))) as server:
29452968
port = server.getsockname()[1]
29462969

29472970
with tempfile.NamedTemporaryFile("w", delete_on_close=False) as connect_script:
29482971
connect_script.write(
2949-
f'import pdb, sys\n'
2950-
f'pdb._connect("localhost", {port}, sys._getframe().f_back)\n'
2972+
textwrap.dedent(
2973+
f"""
2974+
import pdb, sys
2975+
pdb._connect(
2976+
host="localhost",
2977+
port={port},
2978+
frame=sys._getframe(1),
2979+
commands={json.dumps("\n".join(commands))},
2980+
version={_RemotePdb.protocol_version()},
2981+
)
2982+
"""
2983+
)
29512984
)
29522985
connect_script.close()
29532986
sys.remote_exec(pid, connect_script.name)
@@ -3087,7 +3120,7 @@ def main():
30873120
if opts.pid:
30883121
if opts.module:
30893122
parser.error("argument -m: not allowed with argument --pid")
3090-
attach(opts.pid)
3123+
attach(opts.pid, opts.commands)
30913124
return
30923125

30933126
if opts.module:

0 commit comments

Comments
 (0)