@@ -2451,38 +2451,71 @@ sys_is_remote_debug_enabled_impl(PyObject *module)
2451
2451
#endif
2452
2452
}
2453
2453
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
+
2454
2480
static 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]*/
2456
2483
{
2457
- const char * debugger_script_path = PyUnicode_AsUTF8 (script );
2458
- if (debugger_script_path == NULL ) {
2484
+ PyObject * path ;
2485
+ const char * debugger_script_path ;
2486
+
2487
+ if (PyUnicode_FSConverter (script , & path ) < 0 ) {
2459
2488
return NULL ;
2460
2489
}
2461
-
2490
+ debugger_script_path = PyBytes_AS_STRING ( path );
2462
2491
#ifdef MS_WINDOWS
2492
+ PyObject * unicode_path ;
2493
+ if (PyUnicode_FSDecoder (path , & unicode_path ) < 0 ) {
2494
+ goto error ;
2495
+ }
2463
2496
// Use UTF-16 (wide char) version of the path for permission checks
2464
- wchar_t * debugger_script_path_w = PyUnicode_AsWideCharString (script , NULL );
2497
+ wchar_t * debugger_script_path_w = PyUnicode_AsWideCharString (unicode_path , NULL );
2498
+ Py_DECREF (unicode_path );
2465
2499
if (debugger_script_path_w == NULL ) {
2466
- return NULL ;
2500
+ goto error ;
2467
2501
}
2468
-
2469
- // Check file attributes using wide character version (W) instead of ANSI (A)
2470
2502
DWORD attr = GetFileAttributesW (debugger_script_path_w );
2471
- PyMem_Free (debugger_script_path_w );
2472
2503
if (attr == INVALID_FILE_ATTRIBUTES ) {
2473
2504
DWORD err = GetLastError ();
2505
+ PyMem_Free (debugger_script_path_w );
2474
2506
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ) {
2475
2507
PyErr_SetString (PyExc_FileNotFoundError , "Script file does not exist" );
2476
2508
}
2477
2509
else if (err == ERROR_ACCESS_DENIED ) {
2478
2510
PyErr_SetString (PyExc_PermissionError , "Script file cannot be read" );
2479
2511
}
2480
2512
else {
2481
- PyErr_SetFromWindowsErr (0 );
2513
+ PyErr_SetFromWindowsErr (err );
2482
2514
}
2483
- return NULL ;
2515
+ goto error ;
2484
2516
}
2485
- #else
2517
+ PyMem_Free (debugger_script_path_w );
2518
+ #else // MS_WINDOWS
2486
2519
if (access (debugger_script_path , F_OK | R_OK ) != 0 ) {
2487
2520
switch (errno ) {
2488
2521
case ENOENT :
@@ -2494,54 +2527,19 @@ sys_remote_exec_unicode_path(PyObject *module, int pid, PyObject *script)
2494
2527
default :
2495
2528
PyErr_SetFromErrno (PyExc_OSError );
2496
2529
}
2497
- return NULL ;
2530
+ goto error ;
2498
2531
}
2499
- #endif
2500
-
2532
+ #endif // MS_WINDOWS
2501
2533
if (_PySysRemoteDebug_SendExec (pid , 0 , debugger_script_path ) < 0 ) {
2502
- return NULL ;
2534
+ goto error ;
2503
2535
}
2504
2536
2537
+ Py_DECREF (path );
2505
2538
Py_RETURN_NONE ;
2506
- }
2507
-
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
2539
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 ;
2540
+ error :
2541
+ Py_DECREF (path );
2542
+ return NULL ;
2545
2543
}
2546
2544
2547
2545
0 commit comments