blob: a6008efa04b49f1bf60a443af204d5e64ae38c3b [file] [log] [blame]
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00001/* Authors: Gregory P. Smith & Jeffrey Yasskin */
2#include "Python.h"
3#include <unistd.h>
4
5
6#define POSIX_CALL(call) if ((call) == -1) goto error
7
8
9/* Maximum file descriptor, initialized on module load. */
10static long max_fd;
11
12
13/* Given the gc module call gc.enable() and return 0 on success. */
14static int _enable_gc(PyObject *gc_module)
15{
16 PyObject *result;
17 result = PyObject_CallMethod(gc_module, "enable", NULL);
18 if (result == NULL)
19 return 1;
20 Py_DECREF(result);
21 return 0;
22}
23
24
25/*
26 * This function is code executed in the child process immediately after fork
27 * to set things up and call exec().
28 *
29 * All of the code in this function must only use async-signal-safe functions,
30 * listed at `man 7 signal` or
31 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
32 *
33 * This restriction is documented at
34 * http://www.opengroup.org/onlinepubs/009695399/functions/fork.html.
35 */
36static void child_exec(char *const exec_array[],
37 char *const argv[],
38 char *const envp[],
39 const char *cwd,
40 int p2cread, int p2cwrite,
41 int c2pread, int c2pwrite,
42 int errread, int errwrite,
43 int errpipe_read, int errpipe_write,
44 int close_fds, int restore_signals,
45 int call_setsid,
46 PyObject *preexec_fn,
47 PyObject *preexec_fn_args_tuple)
48{
49 int i, saved_errno, fd_num;
50 PyObject *result;
51 const char* err_msg;
52 /* Buffer large enough to hold a hex integer. We can't malloc. */
53 char hex_errno[sizeof(saved_errno)*2+1];
54
55 /* Close parent's pipe ends. */
56 if (p2cwrite != -1) {
57 POSIX_CALL(close(p2cwrite));
58 }
59 if (c2pread != -1) {
60 POSIX_CALL(close(c2pread));
61 }
62 if (errread != -1) {
63 POSIX_CALL(close(errread));
64 }
65 POSIX_CALL(close(errpipe_read));
66
67 /* Dup fds for child. */
68 if (p2cread != -1) {
69 POSIX_CALL(dup2(p2cread, 0)); /* stdin */
70 }
71 if (c2pwrite != -1) {
72 POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */
73 }
74 if (errwrite != -1) {
75 POSIX_CALL(dup2(errwrite, 2)); /* stderr */
76 }
77
78 /* Close pipe fds. Make sure we don't close the same fd more than */
79 /* once, or standard fds. */
80 if (p2cread != -1 && p2cread != 0) {
81 POSIX_CALL(close(p2cread));
82 }
83 if (c2pwrite != -1 && c2pwrite != p2cread && c2pwrite != 1) {
84 POSIX_CALL(close(c2pwrite));
85 }
86 if (errwrite != -1 && errwrite != p2cread &&
87 errwrite != c2pwrite && errwrite != 2) {
88 POSIX_CALL(close(errwrite));
89 }
90
91 /* close() is intentionally not checked for errors here as we are closing */
92 /* a large range of fds, some of which may be invalid. */
93 if (close_fds) {
94 for (fd_num = 3; fd_num < errpipe_write; ++fd_num) {
95 close(fd_num);
96 }
97 for (fd_num = errpipe_write+1; fd_num < max_fd; ++fd_num) {
98 close(fd_num);
99 }
100 }
101
102 if (cwd)
103 POSIX_CALL(chdir(cwd));
104
105 if (restore_signals)
106 _Py_RestoreSignals();
107
108#ifdef HAVE_SETSID
109 if (call_setsid)
110 POSIX_CALL(setsid());
111#endif
112
113 if (preexec_fn != Py_None && preexec_fn_args_tuple) {
114 /* This is where the user has asked us to deadlock their program. */
115 result = PyObject_Call(preexec_fn, preexec_fn_args_tuple, NULL);
116 if (result == NULL) {
117 /* Stringifying the exception or traceback would involve
118 * memory allocation and thus potential for deadlock.
119 * We've already faced potential deadlock by calling back
120 * into Python in the first place, so it probably doesn't
121 * matter but we avoid it to minimize the possibility. */
122 err_msg = "Exception occurred in preexec_fn.";
123 errno = 0; /* We don't want to report an OSError. */
124 goto error;
125 }
126 /* Py_DECREF(result); - We're about to exec so why bother? */
127 }
128
129 /* This loop matches the Lib/os.py _execvpe()'s PATH search when */
130 /* given the executable_list generated by Lib/subprocess.py. */
131 saved_errno = 0;
132 for (i = 0; exec_array[i] != NULL; ++i) {
133 const char *executable = exec_array[i];
134 if (envp) {
135 execve(executable, argv, envp);
136 } else {
137 execv(executable, argv);
138 }
139 if (errno != ENOENT && errno != ENOTDIR && saved_errno == 0) {
140 saved_errno = errno;
141 }
142 }
143 /* Report the first exec error, not the last. */
144 if (saved_errno)
145 errno = saved_errno;
146
147error:
148 saved_errno = errno;
149 /* Report the posix error to our parent process. */
150 if (saved_errno) {
151 char *cur;
152 write(errpipe_write, "OSError:", 8);
153 cur = hex_errno + sizeof(hex_errno);
154 while (saved_errno != 0 && cur > hex_errno) {
155 *--cur = "0123456789ABCDEF"[saved_errno % 16];
156 saved_errno /= 16;
157 }
158 write(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur);
159 write(errpipe_write, ":", 1);
160 /* We can't call strerror(saved_errno). It is not async signal safe.
161 * The parent process will look the error message up. */
162 } else {
163 write(errpipe_write, "RuntimeError:0:", 15);
164 write(errpipe_write, err_msg, strlen(err_msg));
165 }
166}
167
168
169static PyObject *
170subprocess_fork_exec(PyObject* self, PyObject *args)
171{
172 PyObject *gc_module = NULL;
173 PyObject *executable_list, *py_close_fds;
174 PyObject *env_list, *preexec_fn;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000175 PyObject *process_args, *converted_args = NULL, *fast_args = NULL;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000176 PyObject *preexec_fn_args_tuple = NULL;
177 int p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite;
178 int errpipe_read, errpipe_write, close_fds, restore_signals;
179 int call_setsid;
180 const char *cwd;
181 pid_t pid;
182 int need_to_reenable_gc = 0;
183 char *const *exec_array, *const *argv = NULL, *const *envp = NULL;
184 Py_ssize_t arg_num;
185
186 if (!PyArg_ParseTuple(
187 args, "OOOzOiiiiiiiiiiO:fork_exec",
188 &process_args, &executable_list, &py_close_fds, &cwd, &env_list,
189 &p2cread, &p2cwrite, &c2pread, &c2pwrite,
190 &errread, &errwrite, &errpipe_read, &errpipe_write,
191 &restore_signals, &call_setsid, &preexec_fn))
192 return NULL;
193
194 close_fds = PyObject_IsTrue(py_close_fds);
195 if (close_fds && errpipe_write < 3) { /* precondition */
196 PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3");
197 return NULL;
198 }
199
200 /* We need to call gc.disable() when we'll be calling preexec_fn */
201 if (preexec_fn != Py_None) {
202 PyObject *result;
203 gc_module = PyImport_ImportModule("gc");
204 if (gc_module == NULL)
205 return NULL;
206 result = PyObject_CallMethod(gc_module, "isenabled", NULL);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000207 if (result == NULL) {
208 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000209 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000210 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000211 need_to_reenable_gc = PyObject_IsTrue(result);
212 Py_DECREF(result);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000213 if (need_to_reenable_gc == -1) {
214 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000215 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000216 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000217 result = PyObject_CallMethod(gc_module, "disable", NULL);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000218 if (result == NULL) {
219 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000220 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000221 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000222 Py_DECREF(result);
223 }
224
225 exec_array = _PySequence_BytesToCharpArray(executable_list);
226 if (!exec_array)
227 return NULL;
228
229 /* Convert args and env into appropriate arguments for exec() */
230 /* These conversions are done in the parent process to avoid allocating
231 or freeing memory in the child process. */
232 if (process_args != Py_None) {
Gregory P. Smith68f52172010-03-15 06:07:42 +0000233 Py_ssize_t num_args;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000234 /* Equivalent to: */
235 /* tuple(PyUnicode_FSConverter(arg) for arg in process_args) */
Gregory P. Smith68f52172010-03-15 06:07:42 +0000236 fast_args = PySequence_Fast(process_args, "argv must be a tuple");
237 num_args = PySequence_Fast_GET_SIZE(fast_args);
238 converted_args = PyTuple_New(num_args);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000239 if (converted_args == NULL)
240 goto cleanup;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000241 for (arg_num = 0; arg_num < num_args; ++arg_num) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000242 PyObject *borrowed_arg, *converted_arg;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000243 borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000244 if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0)
245 goto cleanup;
246 PyTuple_SET_ITEM(converted_args, arg_num, converted_arg);
247 }
248
249 argv = _PySequence_BytesToCharpArray(converted_args);
250 Py_CLEAR(converted_args);
Gregory P. Smith68f52172010-03-15 06:07:42 +0000251 Py_CLEAR(fast_args);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000252 if (!argv)
253 goto cleanup;
254 }
255
256 if (env_list != Py_None) {
257 envp = _PySequence_BytesToCharpArray(env_list);
258 if (!envp)
259 goto cleanup;
260 }
261
262 if (preexec_fn != Py_None) {
263 preexec_fn_args_tuple = PyTuple_New(0);
264 if (!preexec_fn_args_tuple)
265 goto cleanup;
266 _PyImport_AcquireLock();
267 }
268
269 pid = fork();
270 if (pid == 0) {
271 /* Child process */
272 /*
273 * Code from here to _exit() must only use async-signal-safe functions,
274 * listed at `man 7 signal` or
275 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
276 */
277
278 if (preexec_fn != Py_None) {
279 /* We'll be calling back into Python later so we need to do this.
280 * This call may not be async-signal-safe but neither is calling
281 * back into Python. The user asked us to use hope as a strategy
282 * to avoid deadlock... */
283 PyOS_AfterFork();
284 }
285
286 child_exec(exec_array, argv, envp, cwd,
287 p2cread, p2cwrite, c2pread, c2pwrite,
288 errread, errwrite, errpipe_read, errpipe_write,
289 close_fds, restore_signals, call_setsid,
290 preexec_fn, preexec_fn_args_tuple);
291 _exit(255);
292 return NULL; /* Dead code to avoid a potential compiler warning. */
293 }
294 if (pid == -1) {
295 /* Capture the errno exception before errno can be clobbered. */
296 PyErr_SetFromErrno(PyExc_OSError);
297 }
298 if (preexec_fn != Py_None &&
299 _PyImport_ReleaseLock() < 0 && !PyErr_Occurred()) {
300 PyErr_SetString(PyExc_RuntimeError,
301 "not holding the import lock");
302 }
303
304 /* Parent process */
305 if (envp)
306 _Py_FreeCharPArray(envp);
307 if (argv)
308 _Py_FreeCharPArray(argv);
309 _Py_FreeCharPArray(exec_array);
310
311 /* Reenable gc in the parent process (or if fork failed). */
312 if (need_to_reenable_gc && _enable_gc(gc_module)) {
313 Py_XDECREF(gc_module);
314 return NULL;
315 }
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000316 Py_XDECREF(preexec_fn_args_tuple);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000317 Py_XDECREF(gc_module);
318
319 if (pid == -1)
320 return NULL; /* fork() failed. Exception set earlier. */
321
322 return PyLong_FromPid(pid);
323
324cleanup:
325 if (envp)
326 _Py_FreeCharPArray(envp);
327 if (argv)
328 _Py_FreeCharPArray(argv);
329 _Py_FreeCharPArray(exec_array);
330 Py_XDECREF(converted_args);
Gregory P. Smith68f52172010-03-15 06:07:42 +0000331 Py_XDECREF(fast_args);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000332 Py_XDECREF(preexec_fn_args_tuple);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000333
334 /* Reenable gc if it was disabled. */
335 if (need_to_reenable_gc)
336 _enable_gc(gc_module);
337 Py_XDECREF(gc_module);
338 return NULL;
339}
340
341
342PyDoc_STRVAR(subprocess_fork_exec_doc,
343"fork_exec(args, executable_list, close_fds, cwd, env,\n\
344 p2cread, p2cwrite, c2pread, c2pwrite,\n\
345 errread, errwrite, errpipe_read, errpipe_write,\n\
346 restore_signals, call_setsid, preexec_fn)\n\
347\n\
348Forks a child process, closes parent file descriptors as appropriate in the\n\
349child and dups the few that are needed before calling exec() in the child\n\
350process.\n\
351\n\
352The preexec_fn, if supplied, will be called immediately before exec.\n\
353WARNING: preexec_fn is NOT SAFE if your application uses threads.\n\
354 It may trigger infrequent, difficult to debug deadlocks.\n\
355\n\
356If an error occurs in the child process before the exec, it is\n\
357serialized and written to the errpipe_write fd per subprocess.py.\n\
358\n\
359Returns: the child process's PID.\n\
360\n\
361Raises: Only on an error in the parent process.\n\
362");
363
364
365/* module level code ********************************************************/
366
367PyDoc_STRVAR(module_doc,
368"A POSIX helper for the subprocess module.");
369
370
371static PyMethodDef module_methods[] = {
372 {"fork_exec", subprocess_fork_exec, METH_VARARGS, subprocess_fork_exec_doc},
373 {NULL, NULL} /* sentinel */
374};
375
376
377static struct PyModuleDef _posixsubprocessmodule = {
378 PyModuleDef_HEAD_INIT,
379 "_posixsubprocess",
380 module_doc,
381 -1, /* No memory is needed. */
382 module_methods,
383};
384
385PyMODINIT_FUNC
386PyInit__posixsubprocess(void)
387{
388#ifdef _SC_OPEN_MAX
389 max_fd = sysconf(_SC_OPEN_MAX);
390 if (max_fd == -1)
391#endif
392 max_fd = 256; /* Matches Lib/subprocess.py */
393
394 return PyModule_Create(&_posixsubprocessmodule);
395}