Skip to content

Commit 139b234

Browse files
committed
address code review from Steve
1 parent 18c2e64 commit 139b234

File tree

5 files changed

+54
-24
lines changed

5 files changed

+54
-24
lines changed

Doc/using/cmdline.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,11 @@ Miscellaneous options
604604
.. versionadded:: 3.13
605605

606606
* ``-X disable_remote_debug`` disables the remote debugging support as described
607-
in :pep:`768`. This option is only available on some platforms and will do nothing
607+
in :pep:`768`. This includes both the functionality to schedule code for
608+
execution in another process and the functionality to receive code for
609+
execution in the current process.
610+
611+
This option is only available on some platforms and will do nothing
608612
if is not supported on the current system. See also
609613
:envvar:`PYTHON_DISABLE_REMOTE_DEBUG` and :pep:`768`.
610614

@@ -1170,7 +1174,9 @@ conflict.
11701174
.. envvar:: PYTHON_DISABLE_REMOTE_DEBUG
11711175

11721176
If this variable is set to a non-empty string, it disables the remote
1173-
debugging feature described in :pep:`768`.
1177+
debugging feature described in :pep:`768`. This includes both the functionality
1178+
to schedule code for execution in another process and the functionality to
1179+
receive code for execution in the current process.
11741180

11751181
See also the :option:`-X disable_remote_debug` command-line option.
11761182

Doc/using/configure.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,9 @@ also be used to improve performance.
665665
Deactivate remote debugging support described in :pep:`768` (enabled by default).
666666
When this flag is provided the code that allows the interpreter to schedule the
667667
execution of a Python file in a separate process as described in :pep:`768` is
668-
not compiled.
668+
not compiled. This includes both the functionality to schedule code to be executed
669+
and the functionality to receive code to be executed.
670+
669671

670672
.. versionadded:: next
671673

Doc/whatsnew/3.14.rst

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ PEP 768: Safe external debugger interface for CPython
9797

9898
:pep:`768` introduces a zero-overhead debugging interface that allows debuggers and profilers
9999
to safely attach to running Python processes. This is a significant enhancement to Python's
100-
debugging capabilities, bringing them in line with other major programming languages.
100+
debugging capabilities allowing debuggers to forego unsafe alternatives.
101101

102102
The new interface provides safe execution points for attaching debugger code without modifying
103103
the interpreter's normal execution path or adding runtime overhead. This enables tools to
@@ -124,23 +124,7 @@ Here's a simple example that inspects object types in a running Python process:
124124
# Create a temporary script
125125
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
126126
script_path = f.name
127-
f.write("""
128-
import gc
129-
import collections
130-
131-
# Collect all objects managed by the garbage collector
132-
gc.collect()
133-
134-
# Count objects by type
135-
type_counts = collections.Counter(type(obj).__name__
136-
for obj in gc.get_objects())
137-
138-
# Print the most common types
139-
print("Most common object types in process:")
140-
for type_name, count in type_counts.most_common(10):
141-
print(f" {type_name}: {count}")
142-
""")
143-
127+
f.write("import my_debugger; my_debugger.connect(HOST_PROCESS)")
144128
try:
145129
# Execute in process with PID 1234
146130
print("Behold! An offering:")

Lib/test/test_sys.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,6 +1965,7 @@ def _supports_remote_attaching():
19651965
"Test only runs on Linux, Windows and MacOS")
19661966
@unittest.skipIf(sys.platform == "linux" and not _supports_remote_attaching(),
19671967
"Test only runs on Linux with process_vm_readv support")
1968+
@test.support.cpython_only
19681969
class TestRemoteExec(unittest.TestCase):
19691970
def tearDown(self):
19701971
test.support.reap_children()
@@ -2152,5 +2153,31 @@ def test_remote_exec_invalid_script_path(self):
21522153
with self.assertRaises(OSError):
21532154
sys.remote_exec(os.getpid(), "invalid_script_path")
21542155

2156+
def test_remote_exec_in_process_without_debug_fails_envvar(self):
2157+
"""Test remote exec in a process without remote debugging enabled"""
2158+
script = os_helper.TESTFN + '_remote.py'
2159+
self.addCleanup(os_helper.unlink, script)
2160+
with open(script, 'w') as f:
2161+
f.write('print("Remote script executed successfully!")')
2162+
env = os.environ.copy()
2163+
env['PYTHON_DISABLE_REMOTE_DEBUG'] = '1'
2164+
2165+
_, out, err = assert_python_failure('-c', f'import os, sys; sys.remote_exec(os.getpid(), "{script}")', **env)
2166+
self.assertIn(b"Remote debugging is not enabled", err)
2167+
self.assertEqual(out, b"")
2168+
2169+
def test_remote_exec_in_process_without_debug_fails_xoption(self):
2170+
"""Test remote exec in a process without remote debugging enabled"""
2171+
script = os_helper.TESTFN + '_remote.py'
2172+
self.addCleanup(os_helper.unlink, script)
2173+
with open(script, 'w') as f:
2174+
f.write('print("Remote script executed successfully!")')
2175+
2176+
_, out, err = assert_python_failure('-Xdisable-remote-debug', '-c', f'import os, sys; sys.remote_exec(os.getpid(), "{script}")')
2177+
self.assertIn(b"Remote debugging is not enabled", err)
2178+
self.assertEqual(out, b"")
2179+
2180+
2181+
21552182
if __name__ == "__main__":
21562183
unittest.main()

Python/remote_debugging.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ cleanup_proc_handle(proc_handle_t *handle) {
104104
handle->pid = 0;
105105
}
106106

107-
#ifdef Py_SUPPORTS_REMOTE_DEBUG
107+
#if defined(Py_REMOTE_DEBUG) && defined(Py_SUPPORTS_REMOTE_DEBUG)
108108

109109
#if defined(__APPLE__) && TARGET_OS_OSX
110110
static uintptr_t
@@ -918,15 +918,26 @@ send_exec_to_proc_handle(proc_handle_t *handle, int tid, const char *debugger_sc
918918
return 0;
919919
}
920920

921-
#endif // defined(Py_SUPPORTS_REMOTE_DEBUG)
921+
#endif // defined(Py_REMOTE_DEBUG) && defined(Py_SUPPORTS_REMOTE_DEBUG)
922922

923923
int
924924
_PySysRemoteDebug_SendExec(int pid, int tid, const char *debugger_script_path)
925925
{
926-
#ifndef Py_SUPPORTS_REMOTE_DEBUG
926+
#if !defined(Py_SUPPORTS_REMOTE_DEBUG)
927927
PyErr_SetString(PyExc_RuntimeError, "Remote debugging is not supported on this platform");
928928
return -1;
929+
#elif !defined(Py_REMOTE_DEBUG)
930+
PyErr_SetString(PyExc_RuntimeError, "Remote debugging support has not been compiled in");
931+
return -1;
929932
#else
933+
934+
PyThreadState *tstate = _PyThreadState_GET();
935+
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
936+
if (config->remote_debug != 1) {
937+
PyErr_SetString(PyExc_RuntimeError, "Remote debugging is not enabled");
938+
return -1;
939+
}
940+
930941
proc_handle_t handle;
931942
if (init_proc_handle(&handle, pid) < 0) {
932943
return -1;

0 commit comments

Comments
 (0)