]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-131591: Check for remote debug in PyErr_CheckSignals (#132853)
authorPablo Galindo Salgado <Pablogsal@gmail.com>
Wed, 23 Apr 2025 19:59:41 +0000 (20:59 +0100)
committerGitHub <noreply@github.com>
Wed, 23 Apr 2025 19:59:41 +0000 (20:59 +0100)
For the same reasons as running the GC, this will allow sections that
run in native code for long periods without executing bytecode to also
run the remote debugger protocol without having to wait until bytecode
is executed

Signed-off-by: Pablo Galindo <pablogsal@gmail.com>
Include/internal/pycore_ceval.h
Modules/signalmodule.c
Python/ceval_gil.c

index 96ba54b274c804e7382a04cd04ece3939eef05a1..115dd40b8bdfceecec43929a258c09705640d69d 100644 (file)
@@ -373,6 +373,10 @@ PyAPI_FUNC(_PyStackRef) _PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyS
     #endif
 #endif
 
+#if defined(Py_REMOTE_DEBUG) && defined(Py_SUPPORTS_REMOTE_DEBUG)
+extern int _PyRunRemoteDebugger(PyThreadState *tstate);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index dc6485878b7cb47243a96ba0cff9a43bd1ec2919..54bcd3270ef31ac49f67a59fcaa6ad7934464f0c 100644 (file)
@@ -1777,6 +1777,10 @@ PyErr_CheckSignals(void)
         _Py_RunGC(tstate);
     }
 
+#if defined(Py_REMOTE_DEBUG) && defined(Py_SUPPORTS_REMOTE_DEBUG)
+    _PyRunRemoteDebugger(tstate);
+#endif
+
     if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
         return 0;
     }
index ac254363058ec64fc17361d6a209d319960dfdd9..1040433663361f8474070d6e011061091c5affa6 100644 (file)
@@ -1242,6 +1242,38 @@ static inline void run_remote_debugger_script(const char *path)
         PyErr_FormatUnraisable("Error executing debugger script %s", path);
     }
 }
+
+int _PyRunRemoteDebugger(PyThreadState *tstate)
+{
+    const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
+    if (config->remote_debug == 1
+         && tstate->remote_debugger_support.debugger_pending_call == 1)
+    {
+        tstate->remote_debugger_support.debugger_pending_call = 0;
+
+        // Immediately make a copy in case of a race with another debugger
+        // process that's trying to write to the buffer. At least this way
+        // we'll be internally consistent: what we audit is what we run.
+        const size_t pathsz
+            = sizeof(tstate->remote_debugger_support.debugger_script_path);
+
+        char *path = PyMem_Malloc(pathsz);
+        if (path) {
+            // And don't assume the debugger correctly null terminated it.
+            memcpy(
+                path,
+                tstate->remote_debugger_support.debugger_script_path,
+                pathsz);
+            path[pathsz - 1] = '\0';
+            if (*path) {
+                run_remote_debugger_script(path);
+            }
+            PyMem_Free(path);
+        }
+    }
+    return 0;
+}
+
 #endif
 
 /* Do periodic things, like check for signals and async I/0.
@@ -1372,32 +1404,7 @@ _Py_HandlePending(PyThreadState *tstate)
     }
 
 #if defined(Py_REMOTE_DEBUG) && defined(Py_SUPPORTS_REMOTE_DEBUG)
-    const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
-    if (config->remote_debug == 1
-         && tstate->remote_debugger_support.debugger_pending_call == 1)
-    {
-        tstate->remote_debugger_support.debugger_pending_call = 0;
-
-        // Immediately make a copy in case of a race with another debugger
-        // process that's trying to write to the buffer. At least this way
-        // we'll be internally consistent: what we audit is what we run.
-        const size_t pathsz
-            = sizeof(tstate->remote_debugger_support.debugger_script_path);
-
-        char *path = PyMem_Malloc(pathsz);
-        if (path) {
-            // And don't assume the debugger correctly null terminated it.
-            memcpy(
-                path,
-                tstate->remote_debugger_support.debugger_script_path,
-                pathsz);
-            path[pathsz - 1] = '\0';
-            if (*path) {
-                run_remote_debugger_script(path);
-            }
-            PyMem_Free(path);
-        }
-    }
+    _PyRunRemoteDebugger(tstate);
 #endif
 
     return 0;