blob: bc2f72c7a76b3c2394bd578da47cec4e9e746b1c [file] [log] [blame]
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00001/* Authors: Gregory P. Smith & Jeffrey Yasskin */
2#include "Python.h"
Victor Stinner5572ba72011-05-26 14:10:08 +02003#if defined(HAVE_PIPE2) && !defined(_GNU_SOURCE)
4# define _GNU_SOURCE
Gregory P. Smith51ee2702010-12-13 07:59:39 +00005#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;
Gregory P. Smith14affb82010-12-22 05:22:17 +000056 const char* err_msg = "";
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +000057 /* 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
Ross Lagerwalld98646e2011-07-27 07:16:31 +020072 /* When duping fds, if there arises a situation where one of the fds is
73 either 0, 1 or 2, it is possible that it is overwritten (#12607). */
74 if (c2pwrite == 0)
75 POSIX_CALL(c2pwrite = dup(c2pwrite));
76 if (errwrite == 0 || errwrite == 1)
77 POSIX_CALL(errwrite = dup(errwrite));
78
Antoine Pitrouc9c83ba2011-01-03 18:23:55 +000079 /* Dup fds for child.
80 dup2() removes the CLOEXEC flag but we must do it ourselves if dup2()
81 would be a no-op (issue #10806). */
82 if (p2cread == 0) {
83 int old = fcntl(p2cread, F_GETFD);
84 if (old != -1)
85 fcntl(p2cread, F_SETFD, old & ~FD_CLOEXEC);
86 } else if (p2cread != -1) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +000087 POSIX_CALL(dup2(p2cread, 0)); /* stdin */
88 }
Antoine Pitrouc9c83ba2011-01-03 18:23:55 +000089 if (c2pwrite == 1) {
90 int old = fcntl(c2pwrite, F_GETFD);
91 if (old != -1)
92 fcntl(c2pwrite, F_SETFD, old & ~FD_CLOEXEC);
93 } else if (c2pwrite != -1) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +000094 POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */
95 }
Antoine Pitrouc9c83ba2011-01-03 18:23:55 +000096 if (errwrite == 2) {
97 int old = fcntl(errwrite, F_GETFD);
98 if (old != -1)
99 fcntl(errwrite, F_SETFD, old & ~FD_CLOEXEC);
100 } else if (errwrite != -1) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000101 POSIX_CALL(dup2(errwrite, 2)); /* stderr */
102 }
103
104 /* Close pipe fds. Make sure we don't close the same fd more than */
105 /* once, or standard fds. */
Antoine Pitrouc9c83ba2011-01-03 18:23:55 +0000106 if (p2cread > 2) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000107 POSIX_CALL(close(p2cread));
108 }
Gregory P. Smith81218982011-03-15 14:56:39 -0400109 if (c2pwrite > 2 && c2pwrite != p2cread) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000110 POSIX_CALL(close(c2pwrite));
111 }
Gregory P. Smith81218982011-03-15 14:56:39 -0400112 if (errwrite != c2pwrite && errwrite != p2cread && errwrite > 2) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000113 POSIX_CALL(close(errwrite));
114 }
115
116 /* close() is intentionally not checked for errors here as we are closing */
117 /* a large range of fds, some of which may be invalid. */
118 if (close_fds) {
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000119 Py_ssize_t keep_seq_idx;
120 int start_fd = 3;
121 for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
122 PyObject* py_keep_fd = PySequence_Fast_GET_ITEM(py_fds_to_keep,
123 keep_seq_idx);
124 int keep_fd = PyLong_AsLong(py_keep_fd);
125 if (keep_fd < 0) { /* Negative number, overflow or not a Long. */
126 err_msg = "bad value in fds_to_keep.";
127 errno = 0; /* We don't want to report an OSError. */
128 goto error;
129 }
Gregory P. Smith8edd99d2010-12-14 13:43:30 +0000130 if (keep_fd < start_fd)
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000131 continue;
132 for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) {
133 close(fd_num);
134 }
135 start_fd = keep_fd + 1;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000136 }
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000137 if (start_fd <= max_fd) {
138 for (fd_num = start_fd; fd_num < max_fd; ++fd_num) {
139 close(fd_num);
140 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000141 }
142 }
143
144 if (cwd)
145 POSIX_CALL(chdir(cwd));
146
147 if (restore_signals)
148 _Py_RestoreSignals();
149
150#ifdef HAVE_SETSID
151 if (call_setsid)
152 POSIX_CALL(setsid());
153#endif
154
155 if (preexec_fn != Py_None && preexec_fn_args_tuple) {
156 /* This is where the user has asked us to deadlock their program. */
157 result = PyObject_Call(preexec_fn, preexec_fn_args_tuple, NULL);
158 if (result == NULL) {
159 /* Stringifying the exception or traceback would involve
160 * memory allocation and thus potential for deadlock.
161 * We've already faced potential deadlock by calling back
162 * into Python in the first place, so it probably doesn't
163 * matter but we avoid it to minimize the possibility. */
164 err_msg = "Exception occurred in preexec_fn.";
165 errno = 0; /* We don't want to report an OSError. */
166 goto error;
167 }
168 /* Py_DECREF(result); - We're about to exec so why bother? */
169 }
170
171 /* This loop matches the Lib/os.py _execvpe()'s PATH search when */
172 /* given the executable_list generated by Lib/subprocess.py. */
173 saved_errno = 0;
174 for (i = 0; exec_array[i] != NULL; ++i) {
175 const char *executable = exec_array[i];
176 if (envp) {
177 execve(executable, argv, envp);
178 } else {
179 execv(executable, argv);
180 }
181 if (errno != ENOENT && errno != ENOTDIR && saved_errno == 0) {
182 saved_errno = errno;
183 }
184 }
185 /* Report the first exec error, not the last. */
186 if (saved_errno)
187 errno = saved_errno;
188
189error:
190 saved_errno = errno;
191 /* Report the posix error to our parent process. */
192 if (saved_errno) {
193 char *cur;
194 write(errpipe_write, "OSError:", 8);
195 cur = hex_errno + sizeof(hex_errno);
196 while (saved_errno != 0 && cur > hex_errno) {
197 *--cur = "0123456789ABCDEF"[saved_errno % 16];
198 saved_errno /= 16;
199 }
200 write(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur);
201 write(errpipe_write, ":", 1);
202 /* We can't call strerror(saved_errno). It is not async signal safe.
203 * The parent process will look the error message up. */
204 } else {
205 write(errpipe_write, "RuntimeError:0:", 15);
206 write(errpipe_write, err_msg, strlen(err_msg));
207 }
208}
209
210
211static PyObject *
212subprocess_fork_exec(PyObject* self, PyObject *args)
213{
214 PyObject *gc_module = NULL;
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000215 PyObject *executable_list, *py_close_fds, *py_fds_to_keep;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000216 PyObject *env_list, *preexec_fn;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000217 PyObject *process_args, *converted_args = NULL, *fast_args = NULL;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000218 PyObject *preexec_fn_args_tuple = NULL;
219 int p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite;
220 int errpipe_read, errpipe_write, close_fds, restore_signals;
221 int call_setsid;
Victor Stinner0e59cc32010-04-16 23:49:32 +0000222 PyObject *cwd_obj, *cwd_obj2;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000223 const char *cwd;
224 pid_t pid;
225 int need_to_reenable_gc = 0;
226 char *const *exec_array, *const *argv = NULL, *const *envp = NULL;
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000227 Py_ssize_t arg_num, num_fds_to_keep;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000228
229 if (!PyArg_ParseTuple(
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000230 args, "OOOOOOiiiiiiiiiiO:fork_exec",
231 &process_args, &executable_list, &py_close_fds, &py_fds_to_keep,
Victor Stinner0e59cc32010-04-16 23:49:32 +0000232 &cwd_obj, &env_list,
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000233 &p2cread, &p2cwrite, &c2pread, &c2pwrite,
234 &errread, &errwrite, &errpipe_read, &errpipe_write,
235 &restore_signals, &call_setsid, &preexec_fn))
236 return NULL;
237
238 close_fds = PyObject_IsTrue(py_close_fds);
239 if (close_fds && errpipe_write < 3) { /* precondition */
240 PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3");
241 return NULL;
242 }
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000243 num_fds_to_keep = PySequence_Length(py_fds_to_keep);
244 if (num_fds_to_keep < 0) {
245 PyErr_SetString(PyExc_ValueError, "bad fds_to_keep");
246 return NULL;
247 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000248
249 /* We need to call gc.disable() when we'll be calling preexec_fn */
250 if (preexec_fn != Py_None) {
251 PyObject *result;
252 gc_module = PyImport_ImportModule("gc");
253 if (gc_module == NULL)
254 return NULL;
255 result = PyObject_CallMethod(gc_module, "isenabled", NULL);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000256 if (result == NULL) {
257 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000258 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000259 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000260 need_to_reenable_gc = PyObject_IsTrue(result);
261 Py_DECREF(result);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000262 if (need_to_reenable_gc == -1) {
263 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000264 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000265 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000266 result = PyObject_CallMethod(gc_module, "disable", NULL);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000267 if (result == NULL) {
268 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000269 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000270 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000271 Py_DECREF(result);
272 }
273
274 exec_array = _PySequence_BytesToCharpArray(executable_list);
275 if (!exec_array)
276 return NULL;
277
278 /* Convert args and env into appropriate arguments for exec() */
279 /* These conversions are done in the parent process to avoid allocating
280 or freeing memory in the child process. */
281 if (process_args != Py_None) {
Gregory P. Smith68f52172010-03-15 06:07:42 +0000282 Py_ssize_t num_args;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000283 /* Equivalent to: */
284 /* tuple(PyUnicode_FSConverter(arg) for arg in process_args) */
Gregory P. Smith68f52172010-03-15 06:07:42 +0000285 fast_args = PySequence_Fast(process_args, "argv must be a tuple");
286 num_args = PySequence_Fast_GET_SIZE(fast_args);
287 converted_args = PyTuple_New(num_args);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000288 if (converted_args == NULL)
289 goto cleanup;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000290 for (arg_num = 0; arg_num < num_args; ++arg_num) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000291 PyObject *borrowed_arg, *converted_arg;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000292 borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000293 if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0)
294 goto cleanup;
295 PyTuple_SET_ITEM(converted_args, arg_num, converted_arg);
296 }
297
298 argv = _PySequence_BytesToCharpArray(converted_args);
299 Py_CLEAR(converted_args);
Gregory P. Smith68f52172010-03-15 06:07:42 +0000300 Py_CLEAR(fast_args);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000301 if (!argv)
302 goto cleanup;
303 }
304
305 if (env_list != Py_None) {
306 envp = _PySequence_BytesToCharpArray(env_list);
307 if (!envp)
308 goto cleanup;
309 }
310
311 if (preexec_fn != Py_None) {
312 preexec_fn_args_tuple = PyTuple_New(0);
313 if (!preexec_fn_args_tuple)
314 goto cleanup;
Victor Stinner0e59cc32010-04-16 23:49:32 +0000315 _PyImport_AcquireLock();
316 }
317
318 if (cwd_obj != Py_None) {
319 if (PyUnicode_FSConverter(cwd_obj, &cwd_obj2) == 0)
320 goto cleanup;
Victor Stinnerdcb24032010-04-22 12:08:36 +0000321 cwd = PyBytes_AsString(cwd_obj2);
Victor Stinner0e59cc32010-04-16 23:49:32 +0000322 } else {
323 cwd = NULL;
324 cwd_obj2 = NULL;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000325 }
326
327 pid = fork();
328 if (pid == 0) {
329 /* Child process */
Victor Stinner0e59cc32010-04-16 23:49:32 +0000330 /*
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000331 * Code from here to _exit() must only use async-signal-safe functions,
332 * listed at `man 7 signal` or
333 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
334 */
335
336 if (preexec_fn != Py_None) {
337 /* We'll be calling back into Python later so we need to do this.
338 * This call may not be async-signal-safe but neither is calling
339 * back into Python. The user asked us to use hope as a strategy
340 * to avoid deadlock... */
341 PyOS_AfterFork();
342 }
343
344 child_exec(exec_array, argv, envp, cwd,
345 p2cread, p2cwrite, c2pread, c2pwrite,
346 errread, errwrite, errpipe_read, errpipe_write,
347 close_fds, restore_signals, call_setsid,
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000348 num_fds_to_keep, py_fds_to_keep,
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000349 preexec_fn, preexec_fn_args_tuple);
350 _exit(255);
351 return NULL; /* Dead code to avoid a potential compiler warning. */
352 }
Victor Stinner0e59cc32010-04-16 23:49:32 +0000353 Py_XDECREF(cwd_obj2);
354
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000355 if (pid == -1) {
356 /* Capture the errno exception before errno can be clobbered. */
357 PyErr_SetFromErrno(PyExc_OSError);
358 }
359 if (preexec_fn != Py_None &&
360 _PyImport_ReleaseLock() < 0 && !PyErr_Occurred()) {
361 PyErr_SetString(PyExc_RuntimeError,
362 "not holding the import lock");
363 }
364
365 /* Parent process */
366 if (envp)
367 _Py_FreeCharPArray(envp);
368 if (argv)
369 _Py_FreeCharPArray(argv);
370 _Py_FreeCharPArray(exec_array);
371
372 /* Reenable gc in the parent process (or if fork failed). */
373 if (need_to_reenable_gc && _enable_gc(gc_module)) {
374 Py_XDECREF(gc_module);
375 return NULL;
376 }
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000377 Py_XDECREF(preexec_fn_args_tuple);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000378 Py_XDECREF(gc_module);
379
380 if (pid == -1)
381 return NULL; /* fork() failed. Exception set earlier. */
382
383 return PyLong_FromPid(pid);
384
385cleanup:
386 if (envp)
387 _Py_FreeCharPArray(envp);
388 if (argv)
389 _Py_FreeCharPArray(argv);
390 _Py_FreeCharPArray(exec_array);
391 Py_XDECREF(converted_args);
Gregory P. Smith68f52172010-03-15 06:07:42 +0000392 Py_XDECREF(fast_args);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000393 Py_XDECREF(preexec_fn_args_tuple);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000394
395 /* Reenable gc if it was disabled. */
396 if (need_to_reenable_gc)
397 _enable_gc(gc_module);
398 Py_XDECREF(gc_module);
399 return NULL;
400}
401
402
403PyDoc_STRVAR(subprocess_fork_exec_doc,
404"fork_exec(args, executable_list, close_fds, cwd, env,\n\
405 p2cread, p2cwrite, c2pread, c2pwrite,\n\
406 errread, errwrite, errpipe_read, errpipe_write,\n\
407 restore_signals, call_setsid, preexec_fn)\n\
408\n\
409Forks a child process, closes parent file descriptors as appropriate in the\n\
410child and dups the few that are needed before calling exec() in the child\n\
411process.\n\
412\n\
413The preexec_fn, if supplied, will be called immediately before exec.\n\
414WARNING: preexec_fn is NOT SAFE if your application uses threads.\n\
415 It may trigger infrequent, difficult to debug deadlocks.\n\
416\n\
417If an error occurs in the child process before the exec, it is\n\
418serialized and written to the errpipe_write fd per subprocess.py.\n\
419\n\
420Returns: the child process's PID.\n\
421\n\
422Raises: Only on an error in the parent process.\n\
423");
424
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000425PyDoc_STRVAR(subprocess_cloexec_pipe_doc,
426"cloexec_pipe() -> (read_end, write_end)\n\n\
427Create a pipe whose ends have the cloexec flag set.");
428
429static PyObject *
430subprocess_cloexec_pipe(PyObject *self, PyObject *noargs)
431{
432 int fds[2];
433 int res;
434#ifdef HAVE_PIPE2
435 Py_BEGIN_ALLOW_THREADS
436 res = pipe2(fds, O_CLOEXEC);
437 Py_END_ALLOW_THREADS
Gregory P. Smithabcfcba2011-01-02 20:52:48 +0000438 if (res != 0 && errno == ENOSYS)
439 {
440 if (PyErr_WarnEx(
441 PyExc_RuntimeWarning,
442 "pipe2 set errno ENOSYS; falling "
443 "back to non-atomic pipe+fcntl.", 1) != 0) {
444 return NULL;
445 }
446 {
447#endif
448 /* We hold the GIL which offers some protection from other code calling
449 * fork() before the CLOEXEC flags have been set but we can't guarantee
450 * anything without pipe2(). */
451 long oldflags;
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000452
Gregory P. Smithabcfcba2011-01-02 20:52:48 +0000453 res = pipe(fds);
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000454
Gregory P. Smithabcfcba2011-01-02 20:52:48 +0000455 if (res == 0) {
456 oldflags = fcntl(fds[0], F_GETFD, 0);
457 if (oldflags < 0) res = oldflags;
458 }
459 if (res == 0)
460 res = fcntl(fds[0], F_SETFD, oldflags | FD_CLOEXEC);
461
462 if (res == 0) {
463 oldflags = fcntl(fds[1], F_GETFD, 0);
464 if (oldflags < 0) res = oldflags;
465 }
466 if (res == 0)
467 res = fcntl(fds[1], F_SETFD, oldflags | FD_CLOEXEC);
468#ifdef HAVE_PIPE2
469 }
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000470 }
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000471#endif
472 if (res != 0)
473 return PyErr_SetFromErrno(PyExc_OSError);
474 return Py_BuildValue("(ii)", fds[0], fds[1]);
475}
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000476
477/* module level code ********************************************************/
478
479PyDoc_STRVAR(module_doc,
480"A POSIX helper for the subprocess module.");
481
482
483static PyMethodDef module_methods[] = {
484 {"fork_exec", subprocess_fork_exec, METH_VARARGS, subprocess_fork_exec_doc},
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000485 {"cloexec_pipe", subprocess_cloexec_pipe, METH_NOARGS, subprocess_cloexec_pipe_doc},
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000486 {NULL, NULL} /* sentinel */
487};
488
489
490static struct PyModuleDef _posixsubprocessmodule = {
491 PyModuleDef_HEAD_INIT,
492 "_posixsubprocess",
493 module_doc,
494 -1, /* No memory is needed. */
495 module_methods,
496};
497
498PyMODINIT_FUNC
499PyInit__posixsubprocess(void)
500{
501#ifdef _SC_OPEN_MAX
502 max_fd = sysconf(_SC_OPEN_MAX);
503 if (max_fd == -1)
504#endif
505 max_fd = 256; /* Matches Lib/subprocess.py */
506
507 return PyModule_Create(&_posixsubprocessmodule);
508}