blob: bf10cbb43e13a2c463193d636cb1eaf29b151c54 [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;
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
Antoine Pitrouc9c83ba2011-01-03 18:23:55 +000072 /* Dup fds for child.
73 dup2() removes the CLOEXEC flag but we must do it ourselves if dup2()
74 would be a no-op (issue #10806). */
75 if (p2cread == 0) {
76 int old = fcntl(p2cread, F_GETFD);
77 if (old != -1)
78 fcntl(p2cread, F_SETFD, old & ~FD_CLOEXEC);
79 } else if (p2cread != -1) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +000080 POSIX_CALL(dup2(p2cread, 0)); /* stdin */
81 }
Antoine Pitrouc9c83ba2011-01-03 18:23:55 +000082 if (c2pwrite == 1) {
83 int old = fcntl(c2pwrite, F_GETFD);
84 if (old != -1)
85 fcntl(c2pwrite, F_SETFD, old & ~FD_CLOEXEC);
86 } else if (c2pwrite != -1) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +000087 POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */
88 }
Antoine Pitrouc9c83ba2011-01-03 18:23:55 +000089 if (errwrite == 2) {
90 int old = fcntl(errwrite, F_GETFD);
91 if (old != -1)
92 fcntl(errwrite, F_SETFD, old & ~FD_CLOEXEC);
93 } else if (errwrite != -1) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +000094 POSIX_CALL(dup2(errwrite, 2)); /* stderr */
95 }
96
97 /* Close pipe fds. Make sure we don't close the same fd more than */
98 /* once, or standard fds. */
Antoine Pitrouc9c83ba2011-01-03 18:23:55 +000099 if (p2cread > 2) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000100 POSIX_CALL(close(p2cread));
101 }
Gregory P. Smith81218982011-03-15 14:56:39 -0400102 if (c2pwrite > 2 && c2pwrite != p2cread) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000103 POSIX_CALL(close(c2pwrite));
104 }
Gregory P. Smith81218982011-03-15 14:56:39 -0400105 if (errwrite != c2pwrite && errwrite != p2cread && errwrite > 2) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000106 POSIX_CALL(close(errwrite));
107 }
108
109 /* close() is intentionally not checked for errors here as we are closing */
110 /* a large range of fds, some of which may be invalid. */
111 if (close_fds) {
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000112 Py_ssize_t keep_seq_idx;
113 int start_fd = 3;
114 for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
115 PyObject* py_keep_fd = PySequence_Fast_GET_ITEM(py_fds_to_keep,
116 keep_seq_idx);
117 int keep_fd = PyLong_AsLong(py_keep_fd);
118 if (keep_fd < 0) { /* Negative number, overflow or not a Long. */
119 err_msg = "bad value in fds_to_keep.";
120 errno = 0; /* We don't want to report an OSError. */
121 goto error;
122 }
Gregory P. Smith8edd99d2010-12-14 13:43:30 +0000123 if (keep_fd < start_fd)
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000124 continue;
125 for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) {
126 close(fd_num);
127 }
128 start_fd = keep_fd + 1;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000129 }
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000130 if (start_fd <= max_fd) {
131 for (fd_num = start_fd; fd_num < max_fd; ++fd_num) {
132 close(fd_num);
133 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000134 }
135 }
136
137 if (cwd)
138 POSIX_CALL(chdir(cwd));
139
140 if (restore_signals)
141 _Py_RestoreSignals();
142
143#ifdef HAVE_SETSID
144 if (call_setsid)
145 POSIX_CALL(setsid());
146#endif
147
148 if (preexec_fn != Py_None && preexec_fn_args_tuple) {
149 /* This is where the user has asked us to deadlock their program. */
150 result = PyObject_Call(preexec_fn, preexec_fn_args_tuple, NULL);
151 if (result == NULL) {
152 /* Stringifying the exception or traceback would involve
153 * memory allocation and thus potential for deadlock.
154 * We've already faced potential deadlock by calling back
155 * into Python in the first place, so it probably doesn't
156 * matter but we avoid it to minimize the possibility. */
157 err_msg = "Exception occurred in preexec_fn.";
158 errno = 0; /* We don't want to report an OSError. */
159 goto error;
160 }
161 /* Py_DECREF(result); - We're about to exec so why bother? */
162 }
163
164 /* This loop matches the Lib/os.py _execvpe()'s PATH search when */
165 /* given the executable_list generated by Lib/subprocess.py. */
166 saved_errno = 0;
167 for (i = 0; exec_array[i] != NULL; ++i) {
168 const char *executable = exec_array[i];
169 if (envp) {
170 execve(executable, argv, envp);
171 } else {
172 execv(executable, argv);
173 }
174 if (errno != ENOENT && errno != ENOTDIR && saved_errno == 0) {
175 saved_errno = errno;
176 }
177 }
178 /* Report the first exec error, not the last. */
179 if (saved_errno)
180 errno = saved_errno;
181
182error:
183 saved_errno = errno;
184 /* Report the posix error to our parent process. */
185 if (saved_errno) {
186 char *cur;
187 write(errpipe_write, "OSError:", 8);
188 cur = hex_errno + sizeof(hex_errno);
189 while (saved_errno != 0 && cur > hex_errno) {
190 *--cur = "0123456789ABCDEF"[saved_errno % 16];
191 saved_errno /= 16;
192 }
193 write(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur);
194 write(errpipe_write, ":", 1);
195 /* We can't call strerror(saved_errno). It is not async signal safe.
196 * The parent process will look the error message up. */
197 } else {
198 write(errpipe_write, "RuntimeError:0:", 15);
199 write(errpipe_write, err_msg, strlen(err_msg));
200 }
201}
202
203
204static PyObject *
205subprocess_fork_exec(PyObject* self, PyObject *args)
206{
207 PyObject *gc_module = NULL;
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000208 PyObject *executable_list, *py_close_fds, *py_fds_to_keep;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000209 PyObject *env_list, *preexec_fn;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000210 PyObject *process_args, *converted_args = NULL, *fast_args = NULL;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000211 PyObject *preexec_fn_args_tuple = NULL;
212 int p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite;
213 int errpipe_read, errpipe_write, close_fds, restore_signals;
214 int call_setsid;
Victor Stinner0e59cc32010-04-16 23:49:32 +0000215 PyObject *cwd_obj, *cwd_obj2;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000216 const char *cwd;
217 pid_t pid;
218 int need_to_reenable_gc = 0;
219 char *const *exec_array, *const *argv = NULL, *const *envp = NULL;
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000220 Py_ssize_t arg_num, num_fds_to_keep;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000221
222 if (!PyArg_ParseTuple(
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000223 args, "OOOOOOiiiiiiiiiiO:fork_exec",
224 &process_args, &executable_list, &py_close_fds, &py_fds_to_keep,
Victor Stinner0e59cc32010-04-16 23:49:32 +0000225 &cwd_obj, &env_list,
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000226 &p2cread, &p2cwrite, &c2pread, &c2pwrite,
227 &errread, &errwrite, &errpipe_read, &errpipe_write,
228 &restore_signals, &call_setsid, &preexec_fn))
229 return NULL;
230
231 close_fds = PyObject_IsTrue(py_close_fds);
232 if (close_fds && errpipe_write < 3) { /* precondition */
233 PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3");
234 return NULL;
235 }
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000236 num_fds_to_keep = PySequence_Length(py_fds_to_keep);
237 if (num_fds_to_keep < 0) {
238 PyErr_SetString(PyExc_ValueError, "bad fds_to_keep");
239 return NULL;
240 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000241
242 /* We need to call gc.disable() when we'll be calling preexec_fn */
243 if (preexec_fn != Py_None) {
244 PyObject *result;
245 gc_module = PyImport_ImportModule("gc");
246 if (gc_module == NULL)
247 return NULL;
248 result = PyObject_CallMethod(gc_module, "isenabled", NULL);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000249 if (result == NULL) {
250 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000251 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000252 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000253 need_to_reenable_gc = PyObject_IsTrue(result);
254 Py_DECREF(result);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000255 if (need_to_reenable_gc == -1) {
256 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000257 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000258 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000259 result = PyObject_CallMethod(gc_module, "disable", NULL);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000260 if (result == NULL) {
261 Py_DECREF(gc_module);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000262 return NULL;
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000263 }
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000264 Py_DECREF(result);
265 }
266
267 exec_array = _PySequence_BytesToCharpArray(executable_list);
268 if (!exec_array)
269 return NULL;
270
271 /* Convert args and env into appropriate arguments for exec() */
272 /* These conversions are done in the parent process to avoid allocating
273 or freeing memory in the child process. */
274 if (process_args != Py_None) {
Gregory P. Smith68f52172010-03-15 06:07:42 +0000275 Py_ssize_t num_args;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000276 /* Equivalent to: */
277 /* tuple(PyUnicode_FSConverter(arg) for arg in process_args) */
Gregory P. Smith68f52172010-03-15 06:07:42 +0000278 fast_args = PySequence_Fast(process_args, "argv must be a tuple");
279 num_args = PySequence_Fast_GET_SIZE(fast_args);
280 converted_args = PyTuple_New(num_args);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000281 if (converted_args == NULL)
282 goto cleanup;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000283 for (arg_num = 0; arg_num < num_args; ++arg_num) {
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000284 PyObject *borrowed_arg, *converted_arg;
Gregory P. Smith68f52172010-03-15 06:07:42 +0000285 borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000286 if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0)
287 goto cleanup;
288 PyTuple_SET_ITEM(converted_args, arg_num, converted_arg);
289 }
290
291 argv = _PySequence_BytesToCharpArray(converted_args);
292 Py_CLEAR(converted_args);
Gregory P. Smith68f52172010-03-15 06:07:42 +0000293 Py_CLEAR(fast_args);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000294 if (!argv)
295 goto cleanup;
296 }
297
298 if (env_list != Py_None) {
299 envp = _PySequence_BytesToCharpArray(env_list);
300 if (!envp)
301 goto cleanup;
302 }
303
304 if (preexec_fn != Py_None) {
305 preexec_fn_args_tuple = PyTuple_New(0);
306 if (!preexec_fn_args_tuple)
307 goto cleanup;
Victor Stinner0e59cc32010-04-16 23:49:32 +0000308 _PyImport_AcquireLock();
309 }
310
311 if (cwd_obj != Py_None) {
312 if (PyUnicode_FSConverter(cwd_obj, &cwd_obj2) == 0)
313 goto cleanup;
Victor Stinnerdcb24032010-04-22 12:08:36 +0000314 cwd = PyBytes_AsString(cwd_obj2);
Victor Stinner0e59cc32010-04-16 23:49:32 +0000315 } else {
316 cwd = NULL;
317 cwd_obj2 = NULL;
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000318 }
319
320 pid = fork();
321 if (pid == 0) {
322 /* Child process */
Victor Stinner0e59cc32010-04-16 23:49:32 +0000323 /*
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000324 * Code from here to _exit() must only use async-signal-safe functions,
325 * listed at `man 7 signal` or
326 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
327 */
328
329 if (preexec_fn != Py_None) {
330 /* We'll be calling back into Python later so we need to do this.
331 * This call may not be async-signal-safe but neither is calling
332 * back into Python. The user asked us to use hope as a strategy
333 * to avoid deadlock... */
334 PyOS_AfterFork();
335 }
336
337 child_exec(exec_array, argv, envp, cwd,
338 p2cread, p2cwrite, c2pread, c2pwrite,
339 errread, errwrite, errpipe_read, errpipe_write,
340 close_fds, restore_signals, call_setsid,
Gregory P. Smithd4cc7bf2010-12-04 11:22:11 +0000341 num_fds_to_keep, py_fds_to_keep,
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000342 preexec_fn, preexec_fn_args_tuple);
343 _exit(255);
344 return NULL; /* Dead code to avoid a potential compiler warning. */
345 }
Victor Stinner0e59cc32010-04-16 23:49:32 +0000346 Py_XDECREF(cwd_obj2);
347
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000348 if (pid == -1) {
349 /* Capture the errno exception before errno can be clobbered. */
350 PyErr_SetFromErrno(PyExc_OSError);
351 }
352 if (preexec_fn != Py_None &&
353 _PyImport_ReleaseLock() < 0 && !PyErr_Occurred()) {
354 PyErr_SetString(PyExc_RuntimeError,
355 "not holding the import lock");
356 }
357
358 /* Parent process */
359 if (envp)
360 _Py_FreeCharPArray(envp);
361 if (argv)
362 _Py_FreeCharPArray(argv);
363 _Py_FreeCharPArray(exec_array);
364
365 /* Reenable gc in the parent process (or if fork failed). */
366 if (need_to_reenable_gc && _enable_gc(gc_module)) {
367 Py_XDECREF(gc_module);
368 return NULL;
369 }
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000370 Py_XDECREF(preexec_fn_args_tuple);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000371 Py_XDECREF(gc_module);
372
373 if (pid == -1)
374 return NULL; /* fork() failed. Exception set earlier. */
375
376 return PyLong_FromPid(pid);
377
378cleanup:
379 if (envp)
380 _Py_FreeCharPArray(envp);
381 if (argv)
382 _Py_FreeCharPArray(argv);
383 _Py_FreeCharPArray(exec_array);
384 Py_XDECREF(converted_args);
Gregory P. Smith68f52172010-03-15 06:07:42 +0000385 Py_XDECREF(fast_args);
Gregory P. Smith32ec9da2010-03-19 16:53:08 +0000386 Py_XDECREF(preexec_fn_args_tuple);
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000387
388 /* Reenable gc if it was disabled. */
389 if (need_to_reenable_gc)
390 _enable_gc(gc_module);
391 Py_XDECREF(gc_module);
392 return NULL;
393}
394
395
396PyDoc_STRVAR(subprocess_fork_exec_doc,
397"fork_exec(args, executable_list, close_fds, cwd, env,\n\
398 p2cread, p2cwrite, c2pread, c2pwrite,\n\
399 errread, errwrite, errpipe_read, errpipe_write,\n\
400 restore_signals, call_setsid, preexec_fn)\n\
401\n\
402Forks a child process, closes parent file descriptors as appropriate in the\n\
403child and dups the few that are needed before calling exec() in the child\n\
404process.\n\
405\n\
406The preexec_fn, if supplied, will be called immediately before exec.\n\
407WARNING: preexec_fn is NOT SAFE if your application uses threads.\n\
408 It may trigger infrequent, difficult to debug deadlocks.\n\
409\n\
410If an error occurs in the child process before the exec, it is\n\
411serialized and written to the errpipe_write fd per subprocess.py.\n\
412\n\
413Returns: the child process's PID.\n\
414\n\
415Raises: Only on an error in the parent process.\n\
416");
417
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000418PyDoc_STRVAR(subprocess_cloexec_pipe_doc,
419"cloexec_pipe() -> (read_end, write_end)\n\n\
420Create a pipe whose ends have the cloexec flag set.");
421
422static PyObject *
423subprocess_cloexec_pipe(PyObject *self, PyObject *noargs)
424{
425 int fds[2];
426 int res;
427#ifdef HAVE_PIPE2
428 Py_BEGIN_ALLOW_THREADS
429 res = pipe2(fds, O_CLOEXEC);
430 Py_END_ALLOW_THREADS
Gregory P. Smithabcfcba2011-01-02 20:52:48 +0000431 if (res != 0 && errno == ENOSYS)
432 {
433 if (PyErr_WarnEx(
434 PyExc_RuntimeWarning,
435 "pipe2 set errno ENOSYS; falling "
436 "back to non-atomic pipe+fcntl.", 1) != 0) {
437 return NULL;
438 }
439 {
440#endif
441 /* We hold the GIL which offers some protection from other code calling
442 * fork() before the CLOEXEC flags have been set but we can't guarantee
443 * anything without pipe2(). */
444 long oldflags;
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000445
Gregory P. Smithabcfcba2011-01-02 20:52:48 +0000446 res = pipe(fds);
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000447
Gregory P. Smithabcfcba2011-01-02 20:52:48 +0000448 if (res == 0) {
449 oldflags = fcntl(fds[0], F_GETFD, 0);
450 if (oldflags < 0) res = oldflags;
451 }
452 if (res == 0)
453 res = fcntl(fds[0], F_SETFD, oldflags | FD_CLOEXEC);
454
455 if (res == 0) {
456 oldflags = fcntl(fds[1], F_GETFD, 0);
457 if (oldflags < 0) res = oldflags;
458 }
459 if (res == 0)
460 res = fcntl(fds[1], F_SETFD, oldflags | FD_CLOEXEC);
461#ifdef HAVE_PIPE2
462 }
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000463 }
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000464#endif
465 if (res != 0)
466 return PyErr_SetFromErrno(PyExc_OSError);
467 return Py_BuildValue("(ii)", fds[0], fds[1]);
468}
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000469
470/* module level code ********************************************************/
471
472PyDoc_STRVAR(module_doc,
473"A POSIX helper for the subprocess module.");
474
475
476static PyMethodDef module_methods[] = {
477 {"fork_exec", subprocess_fork_exec, METH_VARARGS, subprocess_fork_exec_doc},
Gregory P. Smith51ee2702010-12-13 07:59:39 +0000478 {"cloexec_pipe", subprocess_cloexec_pipe, METH_NOARGS, subprocess_cloexec_pipe_doc},
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000479 {NULL, NULL} /* sentinel */
480};
481
482
483static struct PyModuleDef _posixsubprocessmodule = {
484 PyModuleDef_HEAD_INIT,
485 "_posixsubprocess",
486 module_doc,
487 -1, /* No memory is needed. */
488 module_methods,
489};
490
491PyMODINIT_FUNC
492PyInit__posixsubprocess(void)
493{
494#ifdef _SC_OPEN_MAX
495 max_fd = sysconf(_SC_OPEN_MAX);
496 if (max_fd == -1)
497#endif
498 max_fd = 256; /* Matches Lib/subprocess.py */
499
500 return PyModule_Create(&_posixsubprocessmodule);
501}