45 """ |
48 """ |
46 def newExecl(path, *args): |
49 def newExecl(path, *args): |
47 """ |
50 """ |
48 Function replacing the 'execl' functions of the os module. |
51 Function replacing the 'execl' functions of the os module. |
49 """ |
52 """ |
50 print(args) |
|
51 import os |
53 import os |
52 if ( |
54 if ( |
53 _debugClient.debugging and |
55 _debugClient.debugging and |
54 _debugClient.multiprocessSupport |
56 _debugClient.multiprocessSupport |
55 ): |
57 ): |
56 args = patchArguments(_debugClient, args) |
58 args = patchArguments(_debugClient, args) |
57 if isPythonProgram(args[0]): |
59 if isPythonProgram(args[0]): |
58 path = args[0] |
60 path = args[0] |
59 print(args) |
|
60 return getattr(os, originalName)(path, *args) |
61 return getattr(os, originalName)(path, *args) |
61 return newExecl |
62 return newExecl |
|
63 |
|
64 |
|
65 def createExecv(originalName): |
|
66 """ |
|
67 Function to patch the 'execv' process creation functions. |
|
68 |
|
69 <ul> |
|
70 <li>os.execv(path, args)</li> |
|
71 <li>os.execvp(file, args)</li> |
|
72 </ul> |
|
73 """ |
|
74 def newExecv(path, args): |
|
75 """ |
|
76 Function replacing the 'execv' functions of the os module. |
|
77 """ |
|
78 import os |
|
79 if ( |
|
80 _debugClient.debugging and |
|
81 _debugClient.multiprocessSupport |
|
82 ): |
|
83 args = patchArguments(_debugClient, args) |
|
84 if isPythonProgram(args[0]): |
|
85 path = args[0] |
|
86 return getattr(os, originalName)(path, args) |
|
87 return newExecv |
|
88 |
|
89 |
|
90 def createExecve(originalName): |
|
91 """ |
|
92 Function to patch the 'execve' process creation functions. |
|
93 |
|
94 <ul> |
|
95 <li>os.execve(path, args, env)</li> |
|
96 <li>os.execvpe(file, args, env)</li> |
|
97 </ul> |
|
98 """ |
|
99 def newExecve(path, args, env): |
|
100 """ |
|
101 Function replacing the 'execve' functions of the os module. |
|
102 """ |
|
103 import os |
|
104 if ( |
|
105 _debugClient.debugging and |
|
106 _debugClient.multiprocessSupport |
|
107 ): |
|
108 args = patchArguments(_debugClient, args) |
|
109 if isPythonProgram(args[0]): |
|
110 path = args[0] |
|
111 return getattr(os, originalName)(path, args, env) |
|
112 return newExecve |
|
113 |
|
114 |
|
115 # TODO: add createSpawn... |
|
116 |
|
117 |
|
118 def createForkExec(originalName): |
|
119 """ |
|
120 Function to patch the 'fork_exec' process creation functions. |
|
121 |
|
122 <ul> |
|
123 <li>_posixsubprocess.fork_exec(args, executable_list, close_fds, |
|
124 ... (13 more))</li> |
|
125 </ul> |
|
126 """ |
|
127 def newForkExec(args, *other_args): |
|
128 """ |
|
129 Function replacing the 'fork_exec' functions of the _posixsubprocess |
|
130 module. |
|
131 """ |
|
132 import _posixsubprocess |
|
133 if ( |
|
134 _debugClient.debugging and |
|
135 _debugClient.multiprocessSupport |
|
136 ): |
|
137 args = patchArguments(_debugClient, args) |
|
138 return getattr(_posixsubprocess, originalName)(args, *other_args) |
|
139 return newForkExec |
|
140 |
|
141 |
|
142 def createFork(original_name): |
|
143 """ |
|
144 Function to patch the 'fork' process creation functions. |
|
145 |
|
146 <ul> |
|
147 <li>os.fork()</li> |
|
148 </ul> |
|
149 """ |
|
150 def new_fork(): |
|
151 """ |
|
152 Function replacing the 'fork' function of the os module. |
|
153 """ |
|
154 import os |
|
155 import sys |
|
156 |
|
157 # A simple fork will result in a new python process |
|
158 isNewPythonProcess = True |
|
159 frame = sys._getframe() |
|
160 |
|
161 multiprocess = ( |
|
162 _debugClient.debugging and _debugClient.multiprocessSupport |
|
163 ) |
|
164 |
|
165 isSubprocessFork = False |
|
166 while frame is not None: |
|
167 if ( |
|
168 frame.f_code.co_name == '_execute_child' and |
|
169 'subprocess' in frame.f_code.co_filename |
|
170 ): |
|
171 isSubprocessFork = True |
|
172 # If we're actually in subprocess.Popen creating a child, it |
|
173 # may result in something which is not a Python process, (so, |
|
174 # we don't want to connect with it in the forked version). |
|
175 executable = frame.f_locals.get('executable') |
|
176 if executable is not None: |
|
177 isNewPythonProcess = False |
|
178 if isPythonProgram(executable): |
|
179 isNewPythonProcess = True |
|
180 break |
|
181 |
|
182 frame = frame.f_back |
|
183 frame = None # Just make sure we don't hold on to it. |
|
184 |
|
185 childProcess = getattr(os, original_name)() # fork |
|
186 if not childProcess: |
|
187 if isNewPythonProcess: |
|
188 sys.settrace(None) |
|
189 sys.setprofile(None) |
|
190 _debugClient.sessionClose(False) |
|
191 (wd, host, port, exceptions, tracePython, redirect, |
|
192 noencoding, fork_auto, fork_child) = _debugClient.startOptions |
|
193 _debugClient.startDebugger( |
|
194 filename=sys.argv[0], |
|
195 host=host, |
|
196 port=port, |
|
197 enableTrace=multiprocess and not isSubprocessFork, |
|
198 exceptions=exceptions, |
|
199 tracePython=tracePython, |
|
200 redirect=redirect, |
|
201 passive=False, |
|
202 multiprocessSupport=multiprocess) |
|
203 return childProcess |
|
204 |
|
205 return new_fork |
|
206 |
|
207 |
|
208 def createCreateProcess(originalName): |
|
209 """ |
|
210 Function to patch the 'CreateProcess' process creation function of |
|
211 Windows. |
|
212 """ |
|
213 def newCreateProcess(appName, cmdline, *args): |
|
214 """ |
|
215 Function replacing the 'CreateProcess' function of the _subprocess |
|
216 or _winapi module. |
|
217 """ |
|
218 try: |
|
219 import _subprocess |
|
220 except ImportError: |
|
221 import _winapi as _subprocess |
|
222 return getattr(_subprocess, originalName)( |
|
223 appName, patchArgumentStringWindows(_debugClient, cmdline), *args) |
|
224 return newCreateProcess |
|
225 |
|
226 |
|
227 # TODO: add 'createFork' |
62 |
228 |
63 |
229 |
64 def patchNewProcessFunctions(multiprocessEnabled, debugClient): |
230 def patchNewProcessFunctions(multiprocessEnabled, debugClient): |
65 """ |
231 """ |
66 Function to patch the process creation functions to support multiprocess |
232 Function to patch the process creation functions to support multiprocess |
82 # patch 'os.exec...()' functions |
248 # patch 'os.exec...()' functions |
83 patchModule(os, "execl", createExecl) |
249 patchModule(os, "execl", createExecl) |
84 patchModule(os, "execle", createExecl) |
250 patchModule(os, "execle", createExecl) |
85 patchModule(os, "execlp", createExecl) |
251 patchModule(os, "execlp", createExecl) |
86 patchModule(os, "execlpe", createExecl) |
252 patchModule(os, "execlpe", createExecl) |
|
253 patchModule(os, "execv", createExecv) |
|
254 patchModule(os, "execve", createExecve) |
|
255 patchModule(os, "execvp", createExecv) |
|
256 patchModule(os, "execvpe", createExecve) |
87 |
257 |
88 # TODO: implement patching of the various functions of the os module |
258 # TODO: implement patching of the various functions of the os module |
89 |
259 |
|
260 if isWindowsPlatform(): |
|
261 try: |
|
262 import _subprocess |
|
263 except ImportError: |
|
264 import _winapi as _subprocess |
|
265 patchModule(_subprocess, 'CreateProcess', createCreateProcess) |
|
266 else: |
|
267 patchModule(os, "fork", createFork) |
|
268 try: |
|
269 import _posixsubprocess |
|
270 patchModule(_posixsubprocess, "fork_exec", createForkExec) |
|
271 except ImportError: |
|
272 pass |
|
273 |
90 _debugClient = debugClient |
274 _debugClient = debugClient |