blob: 36da2e5fa954697bdcabad84ec55526283e45583 [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,
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +000045 int call_setsid, Py_ssize_t num_fds_to_keep,
46 PyObject *py_fds_to_keep,
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +000047 PyObject *preexec_fn,
48 PyObject *preexec_fn_args_tuple)
49{
50 int i, saved_errno, fd_num;
51 PyObject *result;
52 const char* err_msg;
53 /* Buffer large enough to hold a hex integer. We can't malloc. */
54 char hex_errno[sizeof(saved_errno)*2+1];
55
56 /* Close parent's pipe ends. */
57 if (p2cwrite != -1) {
58 POSIX_CALL(close(p2cwrite));
59 }
60 if (c2pread != -1) {
61 POSIX_CALL(close(c2pread));
62 }
63 if (errread != -1) {
64 POSIX_CALL(close(errread));
65 }
66 POSIX_CALL(close(errpipe_read));
67
68 /* Dup fds for child. */
69 if (p2cread != -1) {
70 POSIX_CALL(dup2(p2cread, 0)); /* stdin */
71 }
72 if (c2pwrite != -1) {
73 POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */
74 }
75 if (errwrite != -1) {
76 POSIX_CALL(dup2(errwrite, 2)); /* stderr */
77 }
78
79 /* Close pipe fds. Make sure we don't close the same fd more than */
80 /* once, or standard fds. */
81 if (p2cread != -1 && p2cread != 0) {
82 POSIX_CALL(close(p2cread));
83 }
84 if (c2pwrite != -1 && c2pwrite != p2cread && c2pwrite != 1) {
85 POSIX_CALL(close(c2pwrite));
86 }
87 if (errwrite != -1 && errwrite != p2cread &&
88 errwrite != c2pwrite && errwrite != 2) {
89 POSIX_CALL(close(errwrite));
90 }
91
92 /* close() is intentionally not checked for errors here as we are closing */
93 /* a large range of fds, some of which may be invalid. */
94 if (close_fds) {
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +000095 Py_ssize_t keep_seq_idx;
96 int start_fd = 3;
97 for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
98 PyObject* py_keep_fd = PySequence_Fast_GET_ITEM(py_fds_to_keep,
99 keep_seq_idx);
100 int keep_fd = PyLong_AsLong(py_keep_fd);
101 if (keep_fd < 0) { /* Negative number, overflow or not a Long. */
102 err_msg = "bad value in fds_to_keep.";
103 errno = 0; /* We don't want to report an OSError. */
104 goto error;
105 }
106 if (keep_fd <= start_fd)
107 continue;
108 for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) {
109 close(fd_num);
110 }
111 start_fd = keep_fd + 1;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000112 }
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000113 if (start_fd <= max_fd) {
114 for (fd_num = start_fd; fd_num < max_fd; ++fd_num) {
115 close(fd_num);
116 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000117 }
118 }
119
120 if (cwd)
121 POSIX_CALL(chdir(cwd));
122
123 if (restore_signals)
124 _Py_RestoreSignals();
125
126#ifdef HAVE_SETSID
127 if (call_setsid)
128 POSIX_CALL(setsid());
129#endif
130
131 if (preexec_fn != Py_None && preexec_fn_args_tuple) {
132 /* This is where the user has asked us to deadlock their program. */
133 result = PyObject_Call(preexec_fn, preexec_fn_args_tuple, NULL);
134 if (result == NULL) {
135 /* Stringifying the exception or traceback would involve
136 * memory allocation and thus potential for deadlock.
137 * We've already faced potential deadlock by calling back
138 * into Python in the first place, so it probably doesn't
139 * matter but we avoid it to minimize the possibility. */
140 err_msg = "Exception occurred in preexec_fn.";
141 errno = 0; /* We don't want to report an OSError. */
142 goto error;
143 }
144 /* Py_DECREF(result); - We're about to exec so why bother? */
145 }
146
147 /* This loop matches the Lib/os.py _execvpe()'s PATH search when */
148 /* given the executable_list generated by Lib/subprocess.py. */
149 saved_errno = 0;
150 for (i = 0; exec_array[i] != NULL; ++i) {
151 const char *executable = exec_array[i];
152 if (envp) {
153 execve(executable, argv, envp);
154 } else {
155 execv(executable, argv);
156 }
157 if (errno != ENOENT && errno != ENOTDIR && saved_errno == 0) {
158 saved_errno = errno;
159 }
160 }
161 /* Report the first exec error, not the last. */
162 if (saved_errno)
163 errno = saved_errno;
164
165error:
166 saved_errno = errno;
167 /* Report the posix error to our parent process. */
168 if (saved_errno) {
169 char *cur;
170 write(errpipe_write, "OSError:", 8);
171 cur = hex_errno + sizeof(hex_errno);
172 while (saved_errno != 0 && cur > hex_errno) {
173 *--cur = "0123456789ABCDEF"[saved_errno % 16];
174 saved_errno /= 16;
175 }
176 write(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur);
177 write(errpipe_write, ":", 1);
178 /* We can't call strerror(saved_errno). It is not async signal safe.
179 * The parent process will look the error message up. */
180 } else {
181 write(errpipe_write, "RuntimeError:0:", 15);
182 write(errpipe_write, err_msg, strlen(err_msg));
183 }
184}
185
186
187static PyObject *
188subprocess_fork_exec(PyObject* self, PyObject *args)
189{
190 PyObject *gc_module = NULL;
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000191 PyObject *executable_list, *py_close_fds, *py_fds_to_keep;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000192 PyObject *env_list, *preexec_fn;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000193 PyObject *process_args, *converted_args = NULL, *fast_args = NULL;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000194 PyObject *preexec_fn_args_tuple = NULL;
195 int p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite;
196 int errpipe_read, errpipe_write, close_fds, restore_signals;
197 int call_setsid;
Victor Stinner0e59cc32010-04-16 23:49:32 +0000198 PyObject *cwd_obj, *cwd_obj2;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000199 const char *cwd;
200 pid_t pid;
201 int need_to_reenable_gc = 0;
202 char *const *exec_array, *const *argv = NULL, *const *envp = NULL;
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000203 Py_ssize_t arg_num, num_fds_to_keep;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000204
205 if (!PyArg_ParseTuple(
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000206 args, "OOOOOOiiiiiiiiiiO:fork_exec",
207 &process_args, &executable_list, &py_close_fds, &py_fds_to_keep,
Victor Stinner0e59cc32010-04-16 23:49:32 +0000208 &cwd_obj, &env_list,
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000209 &p2cread, &p2cwrite, &c2pread, &c2pwrite,
210 &errread, &errwrite, &errpipe_read, &errpipe_write,
211 &restore_signals, &call_setsid, &preexec_fn))
212 return NULL;
213
214 close_fds = PyObject_IsTrue(py_close_fds);
215 if (close_fds && errpipe_write < 3) { /* precondition */
216 PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3");
217 return NULL;
218 }
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000219 num_fds_to_keep = PySequence_Length(py_fds_to_keep);
220 if (num_fds_to_keep < 0) {
221 PyErr_SetString(PyExc_ValueError, "bad fds_to_keep");
222 return NULL;
223 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000224
225 /* We need to call gc.disable() when we'll be calling preexec_fn */
226 if (preexec_fn != Py_None) {
227 PyObject *result;
228 gc_module = PyImport_ImportModule("gc");
229 if (gc_module == NULL)
230 return NULL;
231 result = PyObject_CallMethod(gc_module, "isenabled", NULL);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000232 if (result == NULL) {
233 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000234 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000235 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000236 need_to_reenable_gc = PyObject_IsTrue(result);
237 Py_DECREF(result);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000238 if (need_to_reenable_gc == -1) {
239 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000240 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000241 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000242 result = PyObject_CallMethod(gc_module, "disable", NULL);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000243 if (result == NULL) {
244 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000245 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000246 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000247 Py_DECREF(result);
248 }
249
250 exec_array = _PySequence_BytesToCharpArray(executable_list);
251 if (!exec_array)
252 return NULL;
253
254 /* Convert args and env into appropriate arguments for exec() */
255 /* These conversions are done in the parent process to avoid allocating
256 or freeing memory in the child process. */
257 if (process_args != Py_None) {
Gregory P. Smith68f52172010-03-15 06:07:42 +0000258 Py_ssize_t num_args;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000259 /* Equivalent to: */
260 /* tuple(PyUnicode_FSConverter(arg) for arg in process_args) */
Gregory P. Smith68f52172010-03-15 06:07:42 +0000261 fast_args = PySequence_Fast(process_args, "argv must be a tuple");
262 num_args = PySequence_Fast_GET_SIZE(fast_args);
263 converted_args = PyTuple_New(num_args);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000264 if (converted_args == NULL)
265 goto cleanup;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000266 for (arg_num = 0; arg_num < num_args; ++arg_num) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000267 PyObject *borrowed_arg, *converted_arg;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000268 borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000269 if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0)
270 goto cleanup;
271 PyTuple_SET_ITEM(converted_args, arg_num, converted_arg);
272 }
273
274 argv = _PySequence_BytesToCharpArray(converted_args);
275 Py_CLEAR(converted_args);
Gregory P. Smith68f52172010-03-15 06:07:42 +0000276 Py_CLEAR(fast_args);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000277 if (!argv)
278 goto cleanup;
279 }
280
281 if (env_list != Py_None) {
282 envp = _PySequence_BytesToCharpArray(env_list);
283 if (!envp)
284 goto cleanup;
285 }
286
287 if (preexec_fn != Py_None) {
288 preexec_fn_args_tuple = PyTuple_New(0);
289 if (!preexec_fn_args_tuple)
290 goto cleanup;
Victor Stinner0e59cc32010-04-16 23:49:32 +0000291 _PyImport_AcquireLock();
292 }
293
294 if (cwd_obj != Py_None) {
295 if (PyUnicode_FSConverter(cwd_obj, &cwd_obj2) == 0)
296 goto cleanup;
Victor Stinnerdcb24032010-04-22 12:08:36 +0000297 cwd = PyBytes_AsString(cwd_obj2);
Victor Stinner0e59cc32010-04-16 23:49:32 +0000298 } else {
299 cwd = NULL;
300 cwd_obj2 = NULL;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000301 }
302
303 pid = fork();
304 if (pid == 0) {
305 /* Child process */
Victor Stinner0e59cc32010-04-16 23:49:32 +0000306 /*
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000307 * Code from here to _exit() must only use async-signal-safe functions,
308 * listed at `man 7 signal` or
309 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
310 */
311
312 if (preexec_fn != Py_None) {
313 /* We'll be calling back into Python later so we need to do this.
314 * This call may not be async-signal-safe but neither is calling
315 * back into Python. The user asked us to use hope as a strategy
316 * to avoid deadlock... */
317 PyOS_AfterFork();
318 }
319
320 child_exec(exec_array, argv, envp, cwd,
321 p2cread, p2cwrite, c2pread, c2pwrite,
322 errread, errwrite, errpipe_read, errpipe_write,
323 close_fds, restore_signals, call_setsid,
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000324 num_fds_to_keep, py_fds_to_keep,
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000325 preexec_fn, preexec_fn_args_tuple);
326 _exit(255);
327 return NULL; /* Dead code to avoid a potential compiler warning. */
328 }
Victor Stinner0e59cc32010-04-16 23:49:32 +0000329 Py_XDECREF(cwd_obj2);
330
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000331 if (pid == -1) {
332 /* Capture the errno exception before errno can be clobbered. */
333 PyErr_SetFromErrno(PyExc_OSError);
334 }
335 if (preexec_fn != Py_None &&
336 _PyImport_ReleaseLock() < 0 && !PyErr_Occurred()) {
337 PyErr_SetString(PyExc_RuntimeError,
338 "not holding the import lock");
339 }
340
341 /* Parent process */
342 if (envp)
343 _Py_FreeCharPArray(envp);
344 if (argv)
345 _Py_FreeCharPArray(argv);
346 _Py_FreeCharPArray(exec_array);
347
348 /* Reenable gc in the parent process (or if fork failed). */
349 if (need_to_reenable_gc && _enable_gc(gc_module)) {
350 Py_XDECREF(gc_module);
351 return NULL;
352 }
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000353 Py_XDECREF(preexec_fn_args_tuple);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000354 Py_XDECREF(gc_module);
355
356 if (pid == -1)
357 return NULL; /* fork() failed. Exception set earlier. */
358
359 return PyLong_FromPid(pid);
360
361cleanup:
362 if (envp)
363 _Py_FreeCharPArray(envp);
364 if (argv)
365 _Py_FreeCharPArray(argv);
366 _Py_FreeCharPArray(exec_array);
367 Py_XDECREF(converted_args);
Gregory P. Smith68f52172010-03-15 06:07:42 +0000368 Py_XDECREF(fast_args);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000369 Py_XDECREF(preexec_fn_args_tuple);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000370
371 /* Reenable gc if it was disabled. */
372 if (need_to_reenable_gc)
373 _enable_gc(gc_module);
374 Py_XDECREF(gc_module);
375 return NULL;
376}
377
378
379PyDoc_STRVAR(subprocess_fork_exec_doc,
380"fork_exec(args, executable_list, close_fds, cwd, env,\n\
381 p2cread, p2cwrite, c2pread, c2pwrite,\n\
382 errread, errwrite, errpipe_read, errpipe_write,\n\
383 restore_signals, call_setsid, preexec_fn)\n\
384\n\
385Forks a child process, closes parent file descriptors as appropriate in the\n\
386child and dups the few that are needed before calling exec() in the child\n\
387process.\n\
388\n\
389The preexec_fn, if supplied, will be called immediately before exec.\n\
390WARNING: preexec_fn is NOT SAFE if your application uses threads.\n\
391 It may trigger infrequent, difficult to debug deadlocks.\n\
392\n\
393If an error occurs in the child process before the exec, it is\n\
394serialized and written to the errpipe_write fd per subprocess.py.\n\
395\n\
396Returns: the child process's PID.\n\
397\n\
398Raises: Only on an error in the parent process.\n\
399");
400
401
402/* module level code ********************************************************/
403
404PyDoc_STRVAR(module_doc,
405"A POSIX helper for the subprocess module.");
406
407
408static PyMethodDef module_methods[] = {
409 {"fork_exec", subprocess_fork_exec, METH_VARARGS, subprocess_fork_exec_doc},
410 {NULL, NULL} /* sentinel */
411};
412
413
414static struct PyModuleDef _posixsubprocessmodule = {
415 PyModuleDef_HEAD_INIT,
416 "_posixsubprocess",
417 module_doc,
418 -1, /* No memory is needed. */
419 module_methods,
420};
421
422PyMODINIT_FUNC
423PyInit__posixsubprocess(void)
424{
425#ifdef _SC_OPEN_MAX
426 max_fd = sysconf(_SC_OPEN_MAX);
427 if (max_fd == -1)
428#endif
429 max_fd = 256; /* Matches Lib/subprocess.py */
430
431 return PyModule_Create(&_posixsubprocessmodule);
432}