Skip to content

Commit c7e86a1

Browse files
authored
Use sys.remote_exec() to attach to pid, if available (#1986)
* Use sys.remote_exec() to attach to pid, if available * Update usage string
1 parent 698499e commit c7e86a1

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

src/debugpy/server/cli.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
[--log-to <path>] [--log-to-stderr]
3838
[--parent-session-pid <pid>]]
3939
[--adapter-access-token <token>]
40+
[--disable-sys-remote-exec]]
4041
{1}
4142
[<arg>]...
4243
""".format(
@@ -56,6 +57,7 @@ class Options(object):
5657
adapter_access_token = None
5758
config: Dict[str, Any] = {}
5859
parent_session_pid: Union[int, None] = None
60+
disable_sys_remote_exec = False
5961

6062

6163
options = Options()
@@ -186,6 +188,7 @@ def do(arg, it):
186188
("--configure-.+", "<value>", set_config),
187189
("--parent-session-pid", "<pid>", set_arg("parent_session_pid", lambda x: int(x) if x else None)),
188190
("--adapter-access-token", "<token>", set_arg("adapter_access_token")),
191+
("--disable-sys-remote-exec", None, set_const("disable_sys_remote_exec", True)),
189192

190193
# Targets. The "" entry corresponds to positional command line arguments,
191194
# i.e. the ones not preceded by any switch name.
@@ -447,6 +450,37 @@ def attach_to_pid():
447450
.replace("\n", "")
448451
.format(script_dir=script_dir, setup=setup)
449452
)
453+
454+
# attempt pep 768 style code injection
455+
if (not options.disable_sys_remote_exec) and hasattr(sys, "remote_exec"):
456+
tmp_file_path = ""
457+
try:
458+
import tempfile
459+
460+
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
461+
tmp_file_path = tmp_file.name
462+
log.info(
463+
"Attempting to inject code at '{tmp_file_path}' using sys.remote_exec()",
464+
tmp_file_path=tmp_file_path,
465+
)
466+
tmp_file.write(python_code.encode())
467+
tmp_file.write(
468+
"""import os;os.remove("{tmp_file_path}");""".format(
469+
tmp_file_path=tmp_file_path
470+
).encode()
471+
)
472+
tmp_file.flush()
473+
tmp_file.close()
474+
sys.remote_exec(pid, tmp_file_path)
475+
return
476+
except Exception as e:
477+
if os.path.exists(tmp_file_path):
478+
os.remove(tmp_file_path)
479+
log.warning(
480+
'Injecting code using sys.remote_exec() failed with error:\n"{e}"\nWill reattempt using pydevd.\n',
481+
e=e,
482+
)
483+
450484
log.info("Code to be injected: \n{0}", python_code.replace(";", ";\n"))
451485

452486
# pydevd restriction on characters in injected code.

0 commit comments

Comments
 (0)