9 """ |
9 """ |
10 |
10 |
11 import contextlib |
11 import contextlib |
12 |
12 |
13 from DebugUtilities import ( |
13 from DebugUtilities import ( |
14 patchArguments, patchArgumentStringWindows, isPythonProgram, |
14 patchArguments, |
15 isWindowsPlatform |
15 patchArgumentStringWindows, |
|
16 isPythonProgram, |
|
17 isWindowsPlatform, |
16 ) |
18 ) |
17 |
19 |
18 _debugClient = None |
20 _debugClient = None |
19 |
21 |
20 |
22 |
21 def _shallPatch(): |
23 def _shallPatch(): |
22 """ |
24 """ |
23 Function to determine, if the multiprocessing patches should be done. |
25 Function to determine, if the multiprocessing patches should be done. |
24 |
26 |
25 @return flag indicating patching should be performed |
27 @return flag indicating patching should be performed |
26 @rtype bool |
28 @rtype bool |
27 """ |
29 """ |
28 return _debugClient.debugging and _debugClient.multiprocessSupport |
30 return _debugClient.debugging and _debugClient.multiprocessSupport |
29 |
31 |
30 |
32 |
31 def patchModule(module, functionName, createFunction): |
33 def patchModule(module, functionName, createFunction): |
32 """ |
34 """ |
33 Function to replace a function of a module with a modified one. |
35 Function to replace a function of a module with a modified one. |
34 |
36 |
35 @param module reference to the module |
37 @param module reference to the module |
36 @type types.ModuleType |
38 @type types.ModuleType |
37 @param functionName name of the function to be replaced |
39 @param functionName name of the function to be replaced |
38 @type str |
40 @type str |
39 @param createFunction function creating the replacement |
41 @param createFunction function creating the replacement |
40 @type types.FunctionType |
42 @type types.FunctionType |
41 """ |
43 """ |
42 if hasattr(module, functionName): |
44 if hasattr(module, functionName): |
43 originalName = 'original_' + functionName |
45 originalName = "original_" + functionName |
44 if not hasattr(module, originalName): |
46 if not hasattr(module, originalName): |
45 setattr(module, originalName, getattr(module, functionName)) |
47 setattr(module, originalName, getattr(module, functionName)) |
46 setattr(module, functionName, createFunction(originalName)) |
48 setattr(module, functionName, createFunction(originalName)) |
47 |
49 |
48 |
50 |
49 def createExecl(originalName): |
51 def createExecl(originalName): |
50 """ |
52 """ |
51 Function to patch the 'execl' process creation functions. |
53 Function to patch the 'execl' process creation functions. |
52 |
54 |
53 <ul> |
55 <ul> |
54 <li>os.execl(path, arg0, arg1, ...)</li> |
56 <li>os.execl(path, arg0, arg1, ...)</li> |
55 <li>os.execle(path, arg0, arg1, ..., env)</li> |
57 <li>os.execle(path, arg0, arg1, ..., env)</li> |
56 <li>os.execlp(file, arg0, arg1, ...)</li> |
58 <li>os.execlp(file, arg0, arg1, ...)</li> |
57 <li>os.execlpe(file, arg0, arg1, ..., env)</li> |
59 <li>os.execlpe(file, arg0, arg1, ..., env)</li> |
58 </ul> |
60 </ul> |
59 |
61 |
60 @param originalName original name of the function to be patched |
62 @param originalName original name of the function to be patched |
61 @type str |
63 @type str |
62 @return function replacing the original one |
64 @return function replacing the original one |
63 @rtype function |
65 @rtype function |
64 """ |
66 """ |
|
67 |
65 def newExecl(path, *args): |
68 def newExecl(path, *args): |
66 """ |
69 """ |
67 Function replacing the 'execl' functions of the os module. |
70 Function replacing the 'execl' functions of the os module. |
68 """ |
71 """ |
69 import os |
72 import os |
|
73 |
70 if _shallPatch(): |
74 if _shallPatch(): |
71 args = patchArguments(_debugClient, args) |
75 args = patchArguments(_debugClient, args) |
72 if isPythonProgram(args[0]): |
76 if isPythonProgram(args[0]): |
73 path = args[0] |
77 path = args[0] |
74 return getattr(os, originalName)(path, *args) |
78 return getattr(os, originalName)(path, *args) |
|
79 |
75 return newExecl |
80 return newExecl |
76 |
81 |
77 |
82 |
78 def createExecv(originalName): |
83 def createExecv(originalName): |
79 """ |
84 """ |
80 Function to patch the 'execv' process creation functions. |
85 Function to patch the 'execv' process creation functions. |
81 |
86 |
82 <ul> |
87 <ul> |
83 <li>os.execv(path, args)</li> |
88 <li>os.execv(path, args)</li> |
84 <li>os.execvp(file, args)</li> |
89 <li>os.execvp(file, args)</li> |
85 </ul> |
90 </ul> |
86 |
91 |
87 @param originalName original name of the function to be patched |
92 @param originalName original name of the function to be patched |
88 @type str |
93 @type str |
89 @return function replacing the original one |
94 @return function replacing the original one |
90 @rtype function |
95 @rtype function |
91 """ |
96 """ |
|
97 |
92 def newExecv(path, args): |
98 def newExecv(path, args): |
93 """ |
99 """ |
94 Function replacing the 'execv' functions of the os module. |
100 Function replacing the 'execv' functions of the os module. |
95 """ |
101 """ |
96 import os |
102 import os |
|
103 |
97 if _shallPatch(): |
104 if _shallPatch(): |
98 args = patchArguments(_debugClient, args) |
105 args = patchArguments(_debugClient, args) |
99 if isPythonProgram(args[0]): |
106 if isPythonProgram(args[0]): |
100 path = args[0] |
107 path = args[0] |
101 return getattr(os, originalName)(path, args) |
108 return getattr(os, originalName)(path, args) |
|
109 |
102 return newExecv |
110 return newExecv |
103 |
111 |
104 |
112 |
105 def createExecve(originalName): |
113 def createExecve(originalName): |
106 """ |
114 """ |
107 Function to patch the 'execve' process creation functions. |
115 Function to patch the 'execve' process creation functions. |
108 |
116 |
109 <ul> |
117 <ul> |
110 <li>os.execve(path, args, env)</li> |
118 <li>os.execve(path, args, env)</li> |
111 <li>os.execvpe(file, args, env)</li> |
119 <li>os.execvpe(file, args, env)</li> |
112 </ul> |
120 </ul> |
113 |
121 |
114 @param originalName original name of the function to be patched |
122 @param originalName original name of the function to be patched |
115 @type str |
123 @type str |
116 @return function replacing the original one |
124 @return function replacing the original one |
117 @rtype function |
125 @rtype function |
118 """ |
126 """ |
|
127 |
119 def newExecve(path, args, env): |
128 def newExecve(path, args, env): |
120 """ |
129 """ |
121 Function replacing the 'execve' functions of the os module. |
130 Function replacing the 'execve' functions of the os module. |
122 """ |
131 """ |
123 import os |
132 import os |
|
133 |
124 if _shallPatch(): |
134 if _shallPatch(): |
125 args = patchArguments(_debugClient, args) |
135 args = patchArguments(_debugClient, args) |
126 if isPythonProgram(args[0]): |
136 if isPythonProgram(args[0]): |
127 path = args[0] |
137 path = args[0] |
128 return getattr(os, originalName)(path, args, env) |
138 return getattr(os, originalName)(path, args, env) |
|
139 |
129 return newExecve |
140 return newExecve |
130 |
141 |
131 |
142 |
132 def createSpawnl(originalName): |
143 def createSpawnl(originalName): |
133 """ |
144 """ |
134 Function to patch the 'spawnl' process creation functions. |
145 Function to patch the 'spawnl' process creation functions. |
135 |
146 |
136 <ul> |
147 <ul> |
137 <li>os.spawnl(mode, path, arg0, arg1, ...)</li> |
148 <li>os.spawnl(mode, path, arg0, arg1, ...)</li> |
138 <li>os.spawnlp(mode, file, arg0, arg1, ...)</li> |
149 <li>os.spawnlp(mode, file, arg0, arg1, ...)</li> |
139 </ul> |
150 </ul> |
140 |
151 |
141 @param originalName original name of the function to be patched |
152 @param originalName original name of the function to be patched |
142 @type str |
153 @type str |
143 @return function replacing the original one |
154 @return function replacing the original one |
144 @rtype function |
155 @rtype function |
145 """ |
156 """ |
|
157 |
146 def newSpawnl(mode, path, *args): |
158 def newSpawnl(mode, path, *args): |
147 """ |
159 """ |
148 Function replacing the 'spawnl' functions of the os module. |
160 Function replacing the 'spawnl' functions of the os module. |
149 """ |
161 """ |
150 import os |
162 import os |
|
163 |
151 args = patchArguments(_debugClient, args) |
164 args = patchArguments(_debugClient, args) |
152 return getattr(os, originalName)(mode, path, *args) |
165 return getattr(os, originalName)(mode, path, *args) |
|
166 |
153 return newSpawnl |
167 return newSpawnl |
154 |
168 |
155 |
169 |
156 def createSpawnv(originalName): |
170 def createSpawnv(originalName): |
157 """ |
171 """ |
158 Function to patch the 'spawnv' process creation functions. |
172 Function to patch the 'spawnv' process creation functions. |
159 |
173 |
160 <ul> |
174 <ul> |
161 <li>os.spawnv(mode, path, args)</li> |
175 <li>os.spawnv(mode, path, args)</li> |
162 <li>os.spawnvp(mode, file, args)</li> |
176 <li>os.spawnvp(mode, file, args)</li> |
163 </ul> |
177 </ul> |
164 |
178 |
165 @param originalName original name of the function to be patched |
179 @param originalName original name of the function to be patched |
166 @type str |
180 @type str |
167 @return function replacing the original one |
181 @return function replacing the original one |
168 @rtype function |
182 @rtype function |
169 """ |
183 """ |
|
184 |
170 def newSpawnv(mode, path, args): |
185 def newSpawnv(mode, path, args): |
171 """ |
186 """ |
172 Function replacing the 'spawnv' functions of the os module. |
187 Function replacing the 'spawnv' functions of the os module. |
173 """ |
188 """ |
174 import os |
189 import os |
|
190 |
175 args = patchArguments(_debugClient, args) |
191 args = patchArguments(_debugClient, args) |
176 return getattr(os, originalName)(mode, path, args) |
192 return getattr(os, originalName)(mode, path, args) |
|
193 |
177 return newSpawnv |
194 return newSpawnv |
178 |
195 |
179 |
196 |
180 def createSpawnve(originalName): |
197 def createSpawnve(originalName): |
181 """ |
198 """ |
182 Function to patch the 'spawnve' process creation functions. |
199 Function to patch the 'spawnve' process creation functions. |
183 |
200 |
184 <ul> |
201 <ul> |
185 <li>os.spawnve(mode, path, args, env)</li> |
202 <li>os.spawnve(mode, path, args, env)</li> |
186 <li>os.spawnvpe(mode, file, args, env)</li> |
203 <li>os.spawnvpe(mode, file, args, env)</li> |
187 </ul> |
204 </ul> |
188 |
205 |
189 @param originalName original name of the function to be patched |
206 @param originalName original name of the function to be patched |
190 @type str |
207 @type str |
191 @return function replacing the original one |
208 @return function replacing the original one |
192 @rtype function |
209 @rtype function |
193 """ |
210 """ |
|
211 |
194 def newSpawnve(mode, path, args, env): |
212 def newSpawnve(mode, path, args, env): |
195 """ |
213 """ |
196 Function replacing the 'spawnve' functions of the os module. |
214 Function replacing the 'spawnve' functions of the os module. |
197 """ |
215 """ |
198 import os |
216 import os |
|
217 |
199 args = patchArguments(_debugClient, args) |
218 args = patchArguments(_debugClient, args) |
200 return getattr(os, originalName)(mode, path, args, env) |
219 return getattr(os, originalName)(mode, path, args, env) |
|
220 |
201 return newSpawnve |
221 return newSpawnve |
202 |
222 |
203 |
223 |
204 def createPosixSpawn(originalName): |
224 def createPosixSpawn(originalName): |
205 """ |
225 """ |
206 Function to patch the 'posix_spawn' process creation functions. |
226 Function to patch the 'posix_spawn' process creation functions. |
207 |
227 |
208 <ul> |
228 <ul> |
209 <li>os.posix_spawn(path, argv, env, *, file_actions=None, ... |
229 <li>os.posix_spawn(path, argv, env, *, file_actions=None, ... |
210 (6 more))</li> |
230 (6 more))</li> |
211 <li>os.posix_spawnp(path, argv, env, *, file_actions=None, ... |
231 <li>os.posix_spawnp(path, argv, env, *, file_actions=None, ... |
212 (6 more))</li> |
232 (6 more))</li> |
213 </ul> |
233 </ul> |
214 |
234 |
215 @param originalName original name of the function to be patched |
235 @param originalName original name of the function to be patched |
216 @type str |
236 @type str |
217 @return function replacing the original one |
237 @return function replacing the original one |
218 @rtype function |
238 @rtype function |
219 """ |
239 """ |
|
240 |
220 def newPosixSpawn(path, argv, env, **kwargs): |
241 def newPosixSpawn(path, argv, env, **kwargs): |
221 """ |
242 """ |
222 Function replacing the 'posix_spawn' functions of the os module. |
243 Function replacing the 'posix_spawn' functions of the os module. |
223 """ |
244 """ |
224 import os |
245 import os |
|
246 |
225 argv = patchArguments(_debugClient, argv) |
247 argv = patchArguments(_debugClient, argv) |
226 return getattr(os, originalName)(path, argv, env, **kwargs) |
248 return getattr(os, originalName)(path, argv, env, **kwargs) |
|
249 |
227 return newPosixSpawn |
250 return newPosixSpawn |
228 |
251 |
229 |
252 |
230 def createForkExec(originalName): |
253 def createForkExec(originalName): |
231 """ |
254 """ |
232 Function to patch the 'fork_exec' process creation functions. |
255 Function to patch the 'fork_exec' process creation functions. |
233 |
256 |
234 <ul> |
257 <ul> |
235 <li>_posixsubprocess.fork_exec(args, executable_list, close_fds, |
258 <li>_posixsubprocess.fork_exec(args, executable_list, close_fds, |
236 ... (13 more))</li> |
259 ... (13 more))</li> |
237 </ul> |
260 </ul> |
238 |
261 |
239 @param originalName original name of the function to be patched |
262 @param originalName original name of the function to be patched |
240 @type str |
263 @type str |
241 @return function replacing the original one |
264 @return function replacing the original one |
242 @rtype function |
265 @rtype function |
243 """ |
266 """ |
|
267 |
244 def newForkExec(args, *other_args): |
268 def newForkExec(args, *other_args): |
245 """ |
269 """ |
246 Function replacing the 'fork_exec' functions of the _posixsubprocess |
270 Function replacing the 'fork_exec' functions of the _posixsubprocess |
247 module. |
271 module. |
248 """ |
272 """ |
249 import _posixsubprocess |
273 import _posixsubprocess |
|
274 |
250 if _shallPatch(): |
275 if _shallPatch(): |
251 args = patchArguments(_debugClient, args) |
276 args = patchArguments(_debugClient, args) |
252 return getattr(_posixsubprocess, originalName)(args, *other_args) |
277 return getattr(_posixsubprocess, originalName)(args, *other_args) |
|
278 |
253 return newForkExec |
279 return newForkExec |
254 |
280 |
255 |
281 |
256 def createFork(originalName): |
282 def createFork(originalName): |
257 """ |
283 """ |
258 Function to patch the 'fork' process creation functions. |
284 Function to patch the 'fork' process creation functions. |
259 |
285 |
260 <ul> |
286 <ul> |
261 <li>os.fork()</li> |
287 <li>os.fork()</li> |
262 </ul> |
288 </ul> |
263 |
289 |
264 @param originalName original name of the function to be patched |
290 @param originalName original name of the function to be patched |
265 @type str |
291 @type str |
266 @return function replacing the original one |
292 @return function replacing the original one |
267 @rtype function |
293 @rtype function |
268 """ |
294 """ |
|
295 |
269 def newFork(): |
296 def newFork(): |
270 """ |
297 """ |
271 Function replacing the 'fork' function of the os module. |
298 Function replacing the 'fork' function of the os module. |
272 """ |
299 """ |
273 import os |
300 import os |
274 import sys |
301 import sys |
275 |
302 |
276 # A simple fork will result in a new python process |
303 # A simple fork will result in a new python process |
277 isNewPythonProcess = True |
304 isNewPythonProcess = True |
278 frame = sys._getframe() |
305 frame = sys._getframe() |
279 |
306 |
280 multiprocess = _shallPatch() |
307 multiprocess = _shallPatch() |
281 |
308 |
282 isSubprocessFork = False |
309 isSubprocessFork = False |
283 isMultiprocessingPopen = False |
310 isMultiprocessingPopen = False |
284 while frame is not None: |
311 while frame is not None: |
285 if frame.f_code.co_name == "_Popen": |
312 if frame.f_code.co_name == "_Popen": |
286 # fork() was called from multiprocessing; ignore this here |
313 # fork() was called from multiprocessing; ignore this here |
287 # because it is handled in 'MultiprocessingExtension.py'. |
314 # because it is handled in 'MultiprocessingExtension.py'. |
288 isMultiprocessingPopen = True |
315 isMultiprocessingPopen = True |
289 break |
316 break |
290 |
317 |
291 elif ( |
318 elif ( |
292 frame.f_code.co_name == '_execute_child' and |
319 frame.f_code.co_name == "_execute_child" |
293 'subprocess' in frame.f_code.co_filename |
320 and "subprocess" in frame.f_code.co_filename |
294 ): |
321 ): |
295 isSubprocessFork = True |
322 isSubprocessFork = True |
296 # If we're actually in subprocess.Popen creating a child, it |
323 # If we're actually in subprocess.Popen creating a child, it |
297 # may result in something which is not a Python process, (so, |
324 # may result in something which is not a Python process, (so, |
298 # we don't want to connect with it in the forked version). |
325 # we don't want to connect with it in the forked version). |
299 executable = frame.f_locals.get('executable') |
326 executable = frame.f_locals.get("executable") |
300 if executable is not None: |
327 if executable is not None: |
301 isNewPythonProcess = False |
328 isNewPythonProcess = False |
302 if isPythonProgram(executable): |
329 if isPythonProgram(executable): |
303 isNewPythonProcess = True |
330 isNewPythonProcess = True |
304 break |
331 break |
305 |
332 |
306 frame = frame.f_back |
333 frame = frame.f_back |
307 frame = None # Just make sure we don't hold on to it. |
334 frame = None # Just make sure we don't hold on to it. |
308 |
335 |
309 childProcess = getattr(os, originalName)() # fork |
336 childProcess = getattr(os, originalName)() # fork |
310 if ( |
337 if not childProcess and not isMultiprocessingPopen and isNewPythonProcess: |
311 not childProcess and |
338 ( |
312 not isMultiprocessingPopen and |
339 wd, |
313 isNewPythonProcess |
340 host, |
314 ): |
341 port, |
315 (wd, host, port, exceptions, tracePython, redirect, |
342 exceptions, |
316 noencoding) = _debugClient.startOptions |
343 tracePython, |
|
344 redirect, |
|
345 noencoding, |
|
346 ) = _debugClient.startOptions |
317 _debugClient.startDebugger( |
347 _debugClient.startDebugger( |
318 filename=sys.argv[0], |
348 filename=sys.argv[0], |
319 host=host, |
349 host=host, |
320 port=port, |
350 port=port, |
321 enableTrace=multiprocess and not isSubprocessFork, |
351 enableTrace=multiprocess and not isSubprocessFork, |
322 exceptions=exceptions, |
352 exceptions=exceptions, |
323 tracePython=tracePython, |
353 tracePython=tracePython, |
324 redirect=redirect, |
354 redirect=redirect, |
325 passive=False, |
355 passive=False, |
326 multiprocessSupport=multiprocess) |
356 multiprocessSupport=multiprocess, |
|
357 ) |
327 return childProcess |
358 return childProcess |
328 |
359 |
329 return newFork |
360 return newFork |
330 |
361 |
331 |
362 |
332 def createCreateProcess(originalName): |
363 def createCreateProcess(originalName): |
333 """ |
364 """ |
334 Function to patch the 'CreateProcess' process creation function of |
365 Function to patch the 'CreateProcess' process creation function of |
335 Windows. |
366 Windows. |
336 |
367 |
337 @param originalName original name of the function to be patched |
368 @param originalName original name of the function to be patched |
338 @type str |
369 @type str |
339 @return function replacing the original one |
370 @return function replacing the original one |
340 @rtype function |
371 @rtype function |
341 """ |
372 """ |
|
373 |
342 def newCreateProcess(appName, cmdline, *args): |
374 def newCreateProcess(appName, cmdline, *args): |
343 """ |
375 """ |
344 Function replacing the 'CreateProcess' function of the _subprocess |
376 Function replacing the 'CreateProcess' function of the _subprocess |
345 or _winapi module. |
377 or _winapi module. |
346 """ |
378 """ |
347 try: |
379 try: |
348 import _subprocess |
380 import _subprocess |
349 except ImportError: |
381 except ImportError: |
350 import _winapi as _subprocess |
382 import _winapi as _subprocess |
351 return getattr(_subprocess, originalName)( |
383 return getattr(_subprocess, originalName)( |
352 appName, patchArgumentStringWindows(_debugClient, cmdline), *args) |
384 appName, patchArgumentStringWindows(_debugClient, cmdline), *args |
|
385 ) |
|
386 |
353 return newCreateProcess |
387 return newCreateProcess |
354 |
388 |
355 |
389 |
356 def patchNewProcessFunctions(multiprocessEnabled, debugClient): |
390 def patchNewProcessFunctions(multiprocessEnabled, debugClient): |
357 """ |
391 """ |
358 Function to patch the process creation functions to support multiprocess |
392 Function to patch the process creation functions to support multiprocess |
359 debugging. |
393 debugging. |
360 |
394 |
361 @param multiprocessEnabled flag indicating multiprocess support |
395 @param multiprocessEnabled flag indicating multiprocess support |
362 @type bool |
396 @type bool |
363 @param debugClient reference to the debug client object |
397 @param debugClient reference to the debug client object |
364 @type DebugClient |
398 @type DebugClient |
365 """ |
399 """ |
366 global _debugClient |
400 global _debugClient |
367 |
401 |
368 if not multiprocessEnabled: |
402 if not multiprocessEnabled: |
369 # return without patching |
403 # return without patching |
370 return |
404 return |
371 |
405 |
372 import os |
406 import os |
373 import sys |
407 import sys |
374 |
408 |
375 # patch 'os.exec...()' functions |
409 # patch 'os.exec...()' functions |
376 #- patchModule(os, "execl", createExecl) |
410 # - patchModule(os, "execl", createExecl) |
377 #- patchModule(os, "execle", createExecl) |
411 # - patchModule(os, "execle", createExecl) |
378 #- patchModule(os, "execlp", createExecl) |
412 # - patchModule(os, "execlp", createExecl) |
379 #- patchModule(os, "execlpe", createExecl) |
413 # - patchModule(os, "execlpe", createExecl) |
380 #- patchModule(os, "execv", createExecv) |
414 # - patchModule(os, "execv", createExecv) |
381 #- patchModule(os, "execve", createExecve) |
415 # - patchModule(os, "execve", createExecve) |
382 #- patchModule(os, "execvp", createExecv) |
416 # - patchModule(os, "execvp", createExecv) |
383 #- patchModule(os, "execvpe", createExecve) |
417 # - patchModule(os, "execvpe", createExecve) |
384 |
418 |
385 # patch 'os.spawn...()' functions |
419 # patch 'os.spawn...()' functions |
386 patchModule(os, "spawnl", createSpawnl) |
420 patchModule(os, "spawnl", createSpawnl) |
387 patchModule(os, "spawnle", createSpawnl) |
421 patchModule(os, "spawnle", createSpawnl) |
388 patchModule(os, "spawnlp", createSpawnl) |
422 patchModule(os, "spawnlp", createSpawnl) |
389 patchModule(os, "spawnlpe", createSpawnl) |
423 patchModule(os, "spawnlpe", createSpawnl) |
390 patchModule(os, "spawnv", createSpawnv) |
424 patchModule(os, "spawnv", createSpawnv) |
391 patchModule(os, "spawnve", createSpawnve) |
425 patchModule(os, "spawnve", createSpawnve) |
392 patchModule(os, "spawnvp", createSpawnv) |
426 patchModule(os, "spawnvp", createSpawnv) |
393 patchModule(os, "spawnvpe", createSpawnve) |
427 patchModule(os, "spawnvpe", createSpawnve) |
394 |
428 |
395 # patch 'os.posix_spawn...()' functions |
429 # patch 'os.posix_spawn...()' functions |
396 if sys.version_info >= (3, 8) and not isWindowsPlatform(): |
430 if sys.version_info >= (3, 8) and not isWindowsPlatform(): |
397 patchModule(os, "posix_spawn", createPosixSpawn) |
431 patchModule(os, "posix_spawn", createPosixSpawn) |
398 patchModule(os, "posix_spawnp", createPosixSpawn) |
432 patchModule(os, "posix_spawnp", createPosixSpawn) |
399 |
433 |
400 if isWindowsPlatform(): |
434 if isWindowsPlatform(): |
401 try: |
435 try: |
402 import _subprocess |
436 import _subprocess |
403 except ImportError: |
437 except ImportError: |
404 import _winapi as _subprocess |
438 import _winapi as _subprocess |
405 patchModule(_subprocess, 'CreateProcess', createCreateProcess) |
439 patchModule(_subprocess, "CreateProcess", createCreateProcess) |
406 else: |
440 else: |
407 patchModule(os, "fork", createFork) |
441 patchModule(os, "fork", createFork) |
408 with contextlib.suppress(ImportError): |
442 with contextlib.suppress(ImportError): |
409 import _posixsubprocess |
443 import _posixsubprocess |
|
444 |
410 patchModule(_posixsubprocess, "fork_exec", createForkExec) |
445 patchModule(_posixsubprocess, "fork_exec", createForkExec) |
411 |
446 |
412 _debugClient = debugClient |
447 _debugClient = debugClient |