@@ -2451,23 +2451,56 @@ sys_is_remote_debug_enabled_impl(PyObject *module)
24512451#endif 
24522452}
24532453
2454+ /*[clinic input] 
2455+ sys.remote_exec 
2456+ 
2457+     pid: int 
2458+     script: object 
2459+ 
2460+ Executes a file containing Python code in a given remote Python process. 
2461+ 
2462+ This function returns immediately, and the code will be executed by the 
2463+ target process's main thread at the next available opportunity, similarly 
2464+ to how signals are handled. There is no interface to determine when the 
2465+ code has been executed. The caller is responsible for making sure that 
2466+ the file still exists whenever the remote process tries to read it and that 
2467+ it hasn't been overwritten. 
2468+ 
2469+ The remote process must be running a CPython interpreter of the same major 
2470+ and minor version as the local process. If either the local or remote 
2471+ interpreter is pre-release (alpha, beta, or release candidate) then the 
2472+ local and remote interpreters must be the same exact version. 
2473+ 
2474+ Args: 
2475+      pid (int): The process ID of the target Python process. 
2476+      script (str|bytes): The path to a file containing 
2477+          the Python code to be executed. 
2478+ [clinic start generated code]*/ 
2479+ 
24542480static  PyObject  * 
2455- sys_remote_exec_unicode_path (PyObject  * module , int  pid , PyObject  * script )
2481+ sys_remote_exec_impl (PyObject  * module , int  pid , PyObject  * script )
2482+ /*[clinic end generated code: output=7d94c56afe4a52c0 input=39908ca2c5fe1eb0]*/ 
24562483{
2457-     const  char  * debugger_script_path  =  PyUnicode_AsUTF8 (script );
2484+     PyObject  * path ;
2485+     const  char  * debugger_script_path ;
2486+ #ifdef  MS_WINDOWS 
2487+     if  (PyUnicode_FSDecoder (script , & path ) <  0 ) {
2488+         return  NULL ;
2489+     }
2490+     debugger_script_path  =  PyUnicode_AsUTF8 (path );
24582491    if  (debugger_script_path  ==  NULL ) {
2492+         Py_DECREF (path );
24592493        return  NULL ;
24602494    }
2461- 
2462- #ifdef  MS_WINDOWS 
24632495    // Use UTF-16 (wide char) version of the path for permission checks 
2464-     wchar_t  * debugger_script_path_w  =  PyUnicode_AsWideCharString (script , NULL );
2496+     wchar_t  * debugger_script_path_w  =  PyUnicode_AsWideCharString (path , NULL );
24652497    if  (debugger_script_path_w  ==  NULL ) {
2498+         Py_DECREF (path );
24662499        return  NULL ;
24672500    }
2468- 
2469-     // Check file attributes using wide character version (W) instead of ANSI (A) 
2501+     Py_BEGIN_ALLOW_THREADS 
24702502    DWORD  attr  =  GetFileAttributesW (debugger_script_path_w );
2503+     Py_END_ALLOW_THREADS 
24712504    PyMem_Free (debugger_script_path_w );
24722505    if  (attr  ==  INVALID_FILE_ATTRIBUTES ) {
24732506        DWORD  err  =  GetLastError ();
@@ -2478,11 +2511,17 @@ sys_remote_exec_unicode_path(PyObject *module, int pid, PyObject *script)
24782511            PyErr_SetString (PyExc_PermissionError , "Script file cannot be read" );
24792512        }
24802513        else  {
2481-             PyErr_SetFromWindowsErr (0 );
2514+             PyErr_SetFromWindowsErr (err );
24822515        }
2516+         Py_DECREF (path );
24832517        return  NULL ;
24842518    }
2485- #else 
2519+ #else  // MS_WINDOWS 
2520+     if  (PyUnicode_FSConverter (script , & path ) <  0 ) {
2521+         return  NULL ;
2522+     }
2523+     debugger_script_path  =  PyBytes_AS_STRING (path );
2524+ 
24862525    if  (access (debugger_script_path , F_OK  | R_OK ) !=  0 ) {
24872526        switch  (errno ) {
24882527            case  ENOENT :
@@ -2494,56 +2533,19 @@ sys_remote_exec_unicode_path(PyObject *module, int pid, PyObject *script)
24942533            default :
24952534                PyErr_SetFromErrno (PyExc_OSError );
24962535        }
2536+         Py_DECREF (path );
24972537        return  NULL ;
24982538    }
2499- #endif 
2500- 
2539+ #endif  // MS_WINDOWS 
25012540    if  (_PySysRemoteDebug_SendExec (pid , 0 , debugger_script_path ) <  0 ) {
2541+         Py_DECREF (path );
25022542        return  NULL ;
25032543    }
25042544
2545+     Py_DECREF (path );
25052546    Py_RETURN_NONE ;
25062547}
25072548
2508- /*[clinic input] 
2509- sys.remote_exec 
2510- 
2511-     pid: int 
2512-     script: object 
2513- 
2514- Executes a file containing Python code in a given remote Python process. 
2515- 
2516- This function returns immediately, and the code will be executed by the 
2517- target process's main thread at the next available opportunity, similarly 
2518- to how signals are handled. There is no interface to determine when the 
2519- code has been executed. The caller is responsible for making sure that 
2520- the file still exists whenever the remote process tries to read it and that 
2521- it hasn't been overwritten. 
2522- 
2523- The remote process must be running a CPython interpreter of the same major 
2524- and minor version as the local process. If either the local or remote 
2525- interpreter is pre-release (alpha, beta, or release candidate) then the 
2526- local and remote interpreters must be the same exact version. 
2527- 
2528- Args: 
2529-      pid (int): The process ID of the target Python process. 
2530-      script (str|bytes): The path to a file containing 
2531-          the Python code to be executed. 
2532- [clinic start generated code]*/ 
2533- 
2534- static  PyObject  * 
2535- sys_remote_exec_impl (PyObject  * module , int  pid , PyObject  * script )
2536- /*[clinic end generated code: output=7d94c56afe4a52c0 input=39908ca2c5fe1eb0]*/ 
2537- {
2538-     PyObject  * ret  =  NULL ;
2539-     PyObject  * path ;
2540-     if  (PyUnicode_FSDecoder (script , & path )) {
2541-         ret  =  sys_remote_exec_unicode_path (module , pid , path );
2542-         Py_DECREF (path );
2543-     }
2544-     return  ret ;
2545- }
2546- 
25472549
25482550
25492551/*[clinic input] 
0 commit comments