blob: 5f226a851d318ae2d8d18f35c33d0fa96a1e1e16 [file] [log] [blame]
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00001/* Authors: Gregory P. Smith & Jeffrey Yasskin */
2#include "Python.h"
Gregory P. Smith51ee2702010-12-13 07:59:39 +00003#ifdef HAVE_PIPE2
4#define _GNU_SOURCE
5#endif
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00006#include <unistd.h>
Gregory P. Smith51ee2702010-12-13 07:59:39 +00007#include <fcntl.h>
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00008
9
10#define POSIX_CALL(call) if ((call) == -1) goto error
11
12
13/* Maximum file descriptor, initialized on module load. */
14static long max_fd;
15
16
17/* Given the gc module call gc.enable() and return 0 on success. */
18static int _enable_gc(PyObject *gc_module)
19{
20 PyObject *result;
21 result = PyObject_CallMethod(gc_module, "enable", NULL);
22 if (result == NULL)
23 return 1;
24 Py_DECREF(result);
25 return 0;
26}
27
28
29/*
30 * This function is code executed in the child process immediately after fork
31 * to set things up and call exec().
32 *
33 * All of the code in this function must only use async-signal-safe functions,
34 * listed at `man 7 signal` or
35 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
36 *
37 * This restriction is documented at
38 * http://www.opengroup.org/onlinepubs/009695399/functions/fork.html.
39 */
40static void child_exec(char *const exec_array[],
41 char *const argv[],
42 char *const envp[],
43 const char *cwd,
44 int p2cread, int p2cwrite,
45 int c2pread, int c2pwrite,
46 int errread, int errwrite,
47 int errpipe_read, int errpipe_write,
48 int close_fds, int restore_signals,
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +000049 int call_setsid, Py_ssize_t num_fds_to_keep,
50 PyObject *py_fds_to_keep,
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +000051 PyObject *preexec_fn,
52 PyObject *preexec_fn_args_tuple)
53{
54 int i, saved_errno, fd_num;
55 PyObject *result;
56 const char* err_msg;
57 /* Buffer large enough to hold a hex integer. We can't malloc. */
58 char hex_errno[sizeof(saved_errno)*2+1];
59
60 /* Close parent's pipe ends. */
61 if (p2cwrite != -1) {
62 POSIX_CALL(close(p2cwrite));
63 }
64 if (c2pread != -1) {
65 POSIX_CALL(close(c2pread));
66 }
67 if (errread != -1) {
68 POSIX_CALL(close(errread));
69 }
70 POSIX_CALL(close(errpipe_read));
71
72 /* Dup fds for child. */
73 if (p2cread != -1) {
74 POSIX_CALL(dup2(p2cread, 0)); /* stdin */
75 }
76 if (c2pwrite != -1) {
77 POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */
78 }
79 if (errwrite != -1) {
80 POSIX_CALL(dup2(errwrite, 2)); /* stderr */
81 }
82
83 /* Close pipe fds. Make sure we don't close the same fd more than */
84 /* once, or standard fds. */
85 if (p2cread != -1 && p2cread != 0) {
86 POSIX_CALL(close(p2cread));
87 }
88 if (c2pwrite != -1 && c2pwrite != p2cread && c2pwrite != 1) {
89 POSIX_CALL(close(c2pwrite));
90 }
91 if (errwrite != -1 && errwrite != p2cread &&
92 errwrite != c2pwrite && errwrite != 2) {
93 POSIX_CALL(close(errwrite));
94 }
95
96 /* close() is intentionally not checked for errors here as we are closing */
97 /* a large range of fds, some of which may be invalid. */
98 if (close_fds) {
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +000099 Py_ssize_t keep_seq_idx;
100 int start_fd = 3;
101 for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
102 PyObject* py_keep_fd = PySequence_Fast_GET_ITEM(py_fds_to_keep,
103 keep_seq_idx);
104 int keep_fd = PyLong_AsLong(py_keep_fd);
105 if (keep_fd < 0) { /* Negative number, overflow or not a Long. */
106 err_msg = "bad value in fds_to_keep.";
107 errno = 0; /* We don't want to report an OSError. */
108 goto error;
109 }
Gregory P. Smith8edd99d2010-12-14 13:43:30 +0000110 if (keep_fd < start_fd)
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000111 continue;
112 for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) {
113 close(fd_num);
114 }
115 start_fd = keep_fd + 1;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000116 }
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000117 if (start_fd <= max_fd) {
118 for (fd_num = start_fd; fd_num < max_fd; ++fd_num) {
119 close(fd_num);
120 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000121 }
122 }
123
124 if (cwd)
125 POSIX_CALL(chdir(cwd));
126
127 if (restore_signals)
128 _Py_RestoreSignals();
129
130#ifdef HAVE_SETSID
131 if (call_setsid)
132 POSIX_CALL(setsid());
133#endif
134
135 if (preexec_fn != Py_None && preexec_fn_args_tuple) {
136 /* This is where the user has asked us to deadlock their program. */
137 result = PyObject_Call(preexec_fn, preexec_fn_args_tuple, NULL);
138 if (result == NULL) {
139 /* Stringifying the exception or traceback would involve
140 * memory allocation and thus potential for deadlock.
141 * We've already faced potential deadlock by calling back
142 * into Python in the first place, so it probably doesn't
143 * matter but we avoid it to minimize the possibility. */
144 err_msg = "Exception occurred in preexec_fn.";
145 errno = 0; /* We don't want to report an OSError. */
146 goto error;
147 }
148 /* Py_DECREF(result); - We're about to exec so why bother? */
149 }
150
151 /* This loop matches the Lib/os.py _execvpe()'s PATH search when */
152 /* given the executable_list generated by Lib/subprocess.py. */
153 saved_errno = 0;
154 for (i = 0; exec_array[i] != NULL; ++i) {
155 const char *executable = exec_array[i];
156 if (envp) {
157 execve(executable, argv, envp);
158 } else {
159 execv(executable, argv);
160 }
161 if (errno != ENOENT && errno != ENOTDIR && saved_errno == 0) {
162 saved_errno = errno;
163 }
164 }
165 /* Report the first exec error, not the last. */
166 if (saved_errno)
167 errno = saved_errno;
168
169error:
170 saved_errno = errno;
171 /* Report the posix error to our parent process. */
172 if (saved_errno) {
173 char *cur;
174 write(errpipe_write, "OSError:", 8);
175 cur = hex_errno + sizeof(hex_errno);
176 while (saved_errno != 0 && cur > hex_errno) {
177 *--cur = "0123456789ABCDEF"[saved_errno % 16];
178 saved_errno /= 16;
179 }
180 write(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur);
181 write(errpipe_write, ":", 1);
182 /* We can't call strerror(saved_errno). It is not async signal safe.
183 * The parent process will look the error message up. */
184 } else {
185 write(errpipe_write, "RuntimeError:0:", 15);
186 write(errpipe_write, err_msg, strlen(err_msg));
187 }
188}
189
190
191static PyObject *
192subprocess_fork_exec(PyObject* self, PyObject *args)
193{
194 PyObject *gc_module = NULL;
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000195 PyObject *executable_list, *py_close_fds, *py_fds_to_keep;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000196 PyObject *env_list, *preexec_fn;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000197 PyObject *process_args, *converted_args = NULL, *fast_args = NULL;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000198 PyObject *preexec_fn_args_tuple = NULL;
199 int p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite;
200 int errpipe_read, errpipe_write, close_fds, restore_signals;
201 int call_setsid;
Victor Stinner0e59cc32010-04-16 23:49:32 +0000202 PyObject *cwd_obj, *cwd_obj2;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000203 const char *cwd;
204 pid_t pid;
205 int need_to_reenable_gc = 0;
206 char *const *exec_array, *const *argv = NULL, *const *envp = NULL;
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000207 Py_ssize_t arg_num, num_fds_to_keep;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000208
209 if (!PyArg_ParseTuple(
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000210 args, "OOOOOOiiiiiiiiiiO:fork_exec",
211 &process_args, &executable_list, &py_close_fds, &py_fds_to_keep,
Victor Stinner0e59cc32010-04-16 23:49:32 +0000212 &cwd_obj, &env_list,
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000213 &p2cread, &p2cwrite, &c2pread, &c2pwrite,
214 &errread, &errwrite, &errpipe_read, &errpipe_write,
215 &restore_signals, &call_setsid, &preexec_fn))
216 return NULL;
217
218 close_fds = PyObject_IsTrue(py_close_fds);
219 if (close_fds && errpipe_write < 3) { /* precondition */
220 PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3");
221 return NULL;
222 }
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000223 num_fds_to_keep = PySequence_Length(py_fds_to_keep);
224 if (num_fds_to_keep < 0) {
225 PyErr_SetString(PyExc_ValueError, "bad fds_to_keep");
226 return NULL;
227 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000228
229 /* We need to call gc.disable() when we'll be calling preexec_fn */
230 if (preexec_fn != Py_None) {
231 PyObject *result;
232 gc_module = PyImport_ImportModule("gc");
233 if (gc_module == NULL)
234 return NULL;
235 result = PyObject_CallMethod(gc_module, "isenabled", NULL);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000236 if (result == NULL) {
237 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000238 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000239 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000240 need_to_reenable_gc = PyObject_IsTrue(result);
241 Py_DECREF(result);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000242 if (need_to_reenable_gc == -1) {
243 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000244 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000245 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000246 result = PyObject_CallMethod(gc_module, "disable", NULL);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000247 if (result == NULL) {
248 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000249 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000250 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000251 Py_DECREF(result);
252 }
253
254 exec_array = _PySequence_BytesToCharpArray(executable_list);
255 if (!exec_array)
256 return NULL;
257
258 /* Convert args and env into appropriate arguments for exec() */
259 /* These conversions are done in the parent process to avoid allocating
260 or freeing memory in the child process. */
261 if (process_args != Py_None) {
Gregory P. Smith68f52172010-03-15 06:07:42 +0000262 Py_ssize_t num_args;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000263 /* Equivalent to: */
264 /* tuple(PyUnicode_FSConverter(arg) for arg in process_args) */
Gregory P. Smith68f52172010-03-15 06:07:42 +0000265 fast_args = PySequence_Fast(process_args, "argv must be a tuple");
266 num_args = PySequence_Fast_GET_SIZE(fast_args);
267 converted_args = PyTuple_New(num_args);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000268 if (converted_args == NULL)
269 goto cleanup;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000270 for (arg_num = 0; arg_num < num_args; ++arg_num) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000271 PyObject *borrowed_arg, *converted_arg;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000272 borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000273 if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0)
274 goto cleanup;
275 PyTuple_SET_ITEM(converted_args, arg_num, converted_arg);
276 }
277
278 argv = _PySequence_BytesToCharpArray(converted_args);
279 Py_CLEAR(converted_args);
Gregory P. Smith68f52172010-03-15 06:07:42 +0000280 Py_CLEAR(fast_args);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000281 if (!argv)
282 goto cleanup;
283 }
284
285 if (env_list != Py_None) {
286 envp = _PySequence_BytesToCharpArray(env_list);
287 if (!envp)
288 goto cleanup;
289 }
290
291 if (preexec_fn != Py_None) {
292 preexec_fn_args_tuple = PyTuple_New(0);
293 if (!preexec_fn_args_tuple)
294 goto cleanup;
Victor Stinner0e59cc32010-04-16 23:49:32 +0000295 _PyImport_AcquireLock();
296 }
297
298 if (cwd_obj != Py_None) {
299 if (PyUnicode_FSConverter(cwd_obj, &cwd_obj2) == 0)
300 goto cleanup;
Victor Stinnerdcb24032010-04-22 12:08:36 +0000301 cwd = PyBytes_AsString(cwd_obj2);
Victor Stinner0e59cc32010-04-16 23:49:32 +0000302 } else {
303 cwd = NULL;
304 cwd_obj2 = NULL;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000305 }
306
307 pid = fork();
308 if (pid == 0) {
309 /* Child process */
Victor Stinner0e59cc32010-04-16 23:49:32 +0000310 /*
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000311 * Code from here to _exit() must only use async-signal-safe functions,
312 * listed at `man 7 signal` or
313 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
314 */
315
316 if (preexec_fn != Py_None) {
317 /* We'll be calling back into Python later so we need to do this.
318 * This call may not be async-signal-safe but neither is calling
319 * back into Python. The user asked us to use hope as a strategy
320 * to avoid deadlock... */
321 PyOS_AfterFork();
322 }
323
324 child_exec(exec_array, argv, envp, cwd,
325 p2cread, p2cwrite, c2pread, c2pwrite,
326 errread, errwrite, errpipe_read, errpipe_write,
327 close_fds, restore_signals, call_setsid,
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000328 num_fds_to_keep, py_fds_to_keep,
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000329 preexec_fn, preexec_fn_args_tuple);
330 _exit(255);
331 return NULL; /* Dead code to avoid a potential compiler warning. */
332 }
Victor Stinner0e59cc32010-04-16 23:49:32 +0000333 Py_XDECREF(cwd_obj2);
334
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000335 if (pid == -1) {
336 /* Capture the errno exception before errno can be clobbered. */
337 PyErr_SetFromErrno(PyExc_OSError);
338 }
339 if (preexec_fn != Py_None &&
340 _PyImport_ReleaseLock() < 0 && !PyErr_Occurred()) {
341 PyErr_SetString(PyExc_RuntimeError,
342 "not holding the import lock");
343 }
344
345 /* Parent process */
346 if (envp)
347 _Py_FreeCharPArray(envp);
348 if (argv)
349 _Py_FreeCharPArray(argv);
350 _Py_FreeCharPArray(exec_array);
351
352 /* Reenable gc in the parent process (or if fork failed). */
353 if (need_to_reenable_gc && _enable_gc(gc_module)) {
354 Py_XDECREF(gc_module);
355 return NULL;
356 }
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000357 Py_XDECREF(preexec_fn_args_tuple);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000358 Py_XDECREF(gc_module);
359
360 if (pid == -1)
361 return NULL; /* fork() failed. Exception set earlier. */
362
363 return PyLong_FromPid(pid);
364
365cleanup:
366 if (envp)
367 _Py_FreeCharPArray(envp);
368 if (argv)
369 _Py_FreeCharPArray(argv);
370 _Py_FreeCharPArray(exec_array);
371 Py_XDECREF(converted_args);
Gregory P. Smith68f52172010-03-15 06:07:42 +0000372 Py_XDECREF(fast_args);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000373 Py_XDECREF(preexec_fn_args_tuple);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000374
375 /* Reenable gc if it was disabled. */
376 if (need_to_reenable_gc)
377 _enable_gc(gc_module);
378 Py_XDECREF(gc_module);
379 return NULL;
380}
381
382
383PyDoc_STRVAR(subprocess_fork_exec_doc,
384"fork_exec(args, executable_list, close_fds, cwd, env,\n\
385 p2cread, p2cwrite, c2pread, c2pwrite,\n\
386 errread, errwrite, errpipe_read, errpipe_write,\n\
387 restore_signals, call_setsid, preexec_fn)\n\
388\n\
389Forks a child process, closes parent file descriptors as appropriate in the\n\
390child and dups the few that are needed before calling exec() in the child\n\
391process.\n\
392\n\
393The preexec_fn, if supplied, will be called immediately before exec.\n\
394WARNING: preexec_fn is NOT SAFE if your application uses threads.\n\
395 It may trigger infrequent, difficult to debug deadlocks.\n\
396\n\
397If an error occurs in the child process before the exec, it is\n\
398serialized and written to the errpipe_write fd per subprocess.py.\n\
399\n\
400Returns: the child process's PID.\n\
401\n\
402Raises: Only on an error in the parent process.\n\
403");
404
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000405PyDoc_STRVAR(subprocess_cloexec_pipe_doc,
406"cloexec_pipe() -> (read_end, write_end)\n\n\
407Create a pipe whose ends have the cloexec flag set.");
408
409static PyObject *
410subprocess_cloexec_pipe(PyObject *self, PyObject *noargs)
411{
412 int fds[2];
413 int res;
414#ifdef HAVE_PIPE2
415 Py_BEGIN_ALLOW_THREADS
416 res = pipe2(fds, O_CLOEXEC);
417 Py_END_ALLOW_THREADS
418#else
419 /* We hold the GIL which offers some protection from other code calling
420 * fork() before the CLOEXEC flags have been set but we can't guarantee
421 * anything without pipe2(). */
422 long oldflags;
423
424 res = pipe(fds);
425
426 if (res == 0) {
427 oldflags = fcntl(fds[0], F_GETFD, 0);
428 if (oldflags < 0) res = oldflags;
429 }
430 if (res == 0)
431 res = fcntl(fds[0], F_SETFD, oldflags | FD_CLOEXEC);
432
433 if (res == 0) {
434 oldflags = fcntl(fds[1], F_GETFD, 0);
435 if (oldflags < 0) res = oldflags;
436 }
437 if (res == 0)
438 res = fcntl(fds[1], F_SETFD, oldflags | FD_CLOEXEC);
439#endif
440 if (res != 0)
441 return PyErr_SetFromErrno(PyExc_OSError);
442 return Py_BuildValue("(ii)", fds[0], fds[1]);
443}
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000444
445/* module level code ********************************************************/
446
447PyDoc_STRVAR(module_doc,
448"A POSIX helper for the subprocess module.");
449
450
451static PyMethodDef module_methods[] = {
452 {"fork_exec", subprocess_fork_exec, METH_VARARGS, subprocess_fork_exec_doc},
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000453 {"cloexec_pipe", subprocess_cloexec_pipe, METH_NOARGS, subprocess_cloexec_pipe_doc},
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000454 {NULL, NULL} /* sentinel */
455};
456
457
458static struct PyModuleDef _posixsubprocessmodule = {
459 PyModuleDef_HEAD_INIT,
460 "_posixsubprocess",
461 module_doc,
462 -1, /* No memory is needed. */
463 module_methods,
464};
465
466PyMODINIT_FUNC
467PyInit__posixsubprocess(void)
468{
469#ifdef _SC_OPEN_MAX
470 max_fd = sysconf(_SC_OPEN_MAX);
471 if (max_fd == -1)
472#endif
473 max_fd = 256; /* Matches Lib/subprocess.py */
474
475 return PyModule_Create(&_posixsubprocessmodule);
476}