Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: tools/telemetry/third_party/subprocess32/_posixsubprocess.c

Issue 1323303002: [Telemetry] Add timeout to telemetry run_tests (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /* Authors: Gregory P. Smith & Jeffrey Yasskin */
2 #define PY_SSIZE_T_CLEAN
3 #include "Python.h"
4 #if defined(__linux__) && !defined(HAVE_PIPE2)
5 # define HAVE_PIPE2 1 /* From 3.2's configure script, undef if you don't. */
6 #endif
7 #if defined(HAVE_PIPE2) && !defined(_GNU_SOURCE)
8 # define _GNU_SOURCE
9 #endif
10 #include <unistd.h>
11 #include <fcntl.h>
12 #ifdef __linux__
13 # define HAVE_SYS_TYPES_H 1 /* From 3.2's configure script, undef if reqd. */
14 # define HAVE_SYS_SYSCALL_H 1 /* From 3.2's configure script, undef if reqd. */
15 # define HAVE_SYS_DIRENT_H 1 /* From 3.2's configure script, undef if reqd. */
16 #endif
17 #ifdef HAVE_SYS_TYPES_H
18 #include <sys/types.h>
19 #endif
20 #if defined(HAVE_SYS_STAT_H) && defined(__FreeBSD__)
21 #include <sys/stat.h>
22 #endif
23 #ifdef HAVE_SYS_SYSCALL_H
24 #include <sys/syscall.h>
25 #endif
26 #ifdef HAVE_DIRENT_H
27 #include <dirent.h>
28 #endif
29
30 #if defined(__ANDROID__) && !defined(SYS_getdents64)
31 /* Android doesn't expose syscalls, add the definition manually. */
32 # include <sys/linux-syscalls.h>
33 # define SYS_getdents64 __NR_getdents64
34 #endif
35
36 #include "_posixsubprocess_helpers.c"
37
38 #if (PY_VERSION_HEX < 0x02060300)
39 /* These are not public API fuctions until 2.6.3. */
40 static void _PyImport_AcquireLock(void);
41 static int _PyImport_ReleaseLock(void);
42 #endif
43
44 #if defined(sun)
45 /* readdir64 is used to work around Solaris 9 bug 6395699. */
46 # define readdir readdir64
47 # define dirent dirent64
48 # if !defined(HAVE_DIRFD)
49 /* Some versions of Solaris lack dirfd(). */
50 # define dirfd(dirp) ((dirp)->dd_fd)
51 # define HAVE_DIRFD
52 # endif
53 #endif
54
55 #if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__))
56 # define FD_DIR "/dev/fd"
57 #else
58 # define FD_DIR "/proc/self/fd"
59 #endif
60
61 #define POSIX_CALL(call) if ((call) == -1) goto error
62
63
64 /* Maximum file descriptor, initialized on module load. */
65 static long max_fd;
66
67
68 /* Given the gc module call gc.enable() and return 0 on success. */
69 static int
70 _enable_gc(PyObject *gc_module)
71 {
72 PyObject *result;
73 result = PyObject_CallMethod(gc_module, "enable", NULL);
74 if (result == NULL)
75 return 1;
76 Py_DECREF(result);
77 return 0;
78 }
79
80
81 /* Convert ASCII to a positive int, no libc call. no overflow. -1 on error. */
82 static int
83 _pos_int_from_ascii(char *name)
84 {
85 int num = 0;
86 while (*name >= '0' && *name <= '9') {
87 num = num * 10 + (*name - '0');
88 ++name;
89 }
90 if (*name)
91 return -1; /* Non digit found, not a number. */
92 return num;
93 }
94
95
96 #if defined(__FreeBSD__)
97 /* When /dev/fd isn't mounted it is often a static directory populated
98 * with 0 1 2 or entries for 0 .. 63 on FreeBSD, NetBSD and OpenBSD.
99 * NetBSD and OpenBSD have a /proc fs available (though not necessarily
100 * mounted) and do not have fdescfs for /dev/fd. MacOS X has a devfs
101 * that properly supports /dev/fd.
102 */
103 static int
104 _is_fdescfs_mounted_on_dev_fd()
105 {
106 struct stat dev_stat;
107 struct stat dev_fd_stat;
108 if (stat("/dev", &dev_stat) != 0)
109 return 0;
110 if (stat(FD_DIR, &dev_fd_stat) != 0)
111 return 0;
112 if (dev_stat.st_dev == dev_fd_stat.st_dev)
113 return 0; /* / == /dev == /dev/fd means it is static. #fail */
114 return 1;
115 }
116 #endif
117
118
119 /* Returns 1 if there is a problem with fd_sequence, 0 otherwise. */
120 static int
121 _sanity_check_python_fd_sequence(PyObject *fd_sequence)
122 {
123 Py_ssize_t seq_idx, seq_len = PySequence_Length(fd_sequence);
124 long prev_fd = -1;
125 for (seq_idx = 0; seq_idx < seq_len; ++seq_idx) {
126 PyObject* py_fd = PySequence_Fast_GET_ITEM(fd_sequence, seq_idx);
127 long iter_fd = PyLong_AsLong(py_fd);
128 if (iter_fd < 0 || iter_fd < prev_fd || iter_fd > INT_MAX) {
129 /* Negative, overflow, not a Long, unsorted, too big for a fd. */
130 return 1;
131 }
132 }
133 return 0;
134 }
135
136
137 /* Is fd found in the sorted Python Sequence? */
138 static int
139 _is_fd_in_sorted_fd_sequence(int fd, PyObject *fd_sequence)
140 {
141 /* Binary search. */
142 Py_ssize_t search_min = 0;
143 Py_ssize_t search_max = PySequence_Length(fd_sequence) - 1;
144 if (search_max < 0)
145 return 0;
146 do {
147 long middle = (search_min + search_max) / 2;
148 long middle_fd = PyLong_AsLong(
149 PySequence_Fast_GET_ITEM(fd_sequence, middle));
150 if (fd == middle_fd)
151 return 1;
152 if (fd > middle_fd)
153 search_min = middle + 1;
154 else
155 search_max = middle - 1;
156 } while (search_min <= search_max);
157 return 0;
158 }
159
160
161 /* Close all file descriptors in the range start_fd inclusive to
162 * end_fd exclusive except for those in py_fds_to_keep. If the
163 * range defined by [start_fd, end_fd) is large this will take a
164 * long time as it calls close() on EVERY possible fd.
165 */
166 static void
167 _close_fds_by_brute_force(int start_fd, int end_fd, PyObject *py_fds_to_keep)
168 {
169 Py_ssize_t num_fds_to_keep = PySequence_Length(py_fds_to_keep);
170 Py_ssize_t keep_seq_idx;
171 int fd_num;
172 /* As py_fds_to_keep is sorted we can loop through the list closing
173 * fds inbetween any in the keep list falling within our range. */
174 for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
175 PyObject* py_keep_fd = PySequence_Fast_GET_ITEM(py_fds_to_keep,
176 keep_seq_idx);
177 int keep_fd = PyLong_AsLong(py_keep_fd);
178 if (keep_fd < start_fd)
179 continue;
180 for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) {
181 while (close(fd_num) < 0 && errno == EINTR);
182 }
183 start_fd = keep_fd + 1;
184 }
185 if (start_fd <= end_fd) {
186 for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
187 while (close(fd_num) < 0 && errno == EINTR);
188 }
189 }
190 }
191
192
193 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
194 /* It doesn't matter if d_name has room for NAME_MAX chars; we're using this
195 * only to read a directory of short file descriptor number names. The kernel
196 * will return an error if we didn't give it enough space. Highly Unlikely.
197 * This structure is very old and stable: It will not change unless the kernel
198 * chooses to break compatibility with all existing binaries. Highly Unlikely.
199 */
200 struct linux_dirent64 {
201 unsigned long long d_ino;
202 long long d_off;
203 unsigned short d_reclen; /* Length of this linux_dirent */
204 unsigned char d_type;
205 char d_name[256]; /* Filename (null-terminated) */
206 };
207
208 /* Close all open file descriptors in the range start_fd inclusive to end_fd
209 * exclusive. Do not close any in the sorted py_fds_to_keep list.
210 *
211 * This version is async signal safe as it does not make any unsafe C library
212 * calls, malloc calls or handle any locks. It is _unfortunate_ to be forced
213 * to resort to making a kernel system call directly but this is the ONLY api
214 * available that does no harm. opendir/readdir/closedir perform memory
215 * allocation and locking so while they usually work they are not guaranteed
216 * to (especially if you have replaced your malloc implementation). A version
217 * of this function that uses those can be found in the _maybe_unsafe variant.
218 *
219 * This is Linux specific because that is all I am ready to test it on. It
220 * should be easy to add OS specific dirent or dirent64 structures and modify
221 * it with some cpp #define magic to work on other OSes as well if you want.
222 */
223 static void
224 _close_open_fd_range_safe(int start_fd, int end_fd, PyObject* py_fds_to_keep)
225 {
226 int fd_dir_fd;
227 if (start_fd >= end_fd)
228 return;
229 #ifdef O_CLOEXEC
230 fd_dir_fd = open(FD_DIR, O_RDONLY | O_CLOEXEC, 0);
231 #else
232 fd_dir_fd = open(FD_DIR, O_RDONLY, 0);
233 #ifdef FD_CLOEXEC
234 {
235 int old = fcntl(fd_dir_fd, F_GETFD);
236 if (old != -1)
237 fcntl(fd_dir_fd, F_SETFD, old | FD_CLOEXEC);
238 }
239 #endif
240 #endif
241 if (fd_dir_fd == -1) {
242 /* No way to get a list of open fds. */
243 _close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep);
244 return;
245 } else {
246 char buffer[sizeof(struct linux_dirent64)];
247 int bytes;
248 while ((bytes = syscall(SYS_getdents64, fd_dir_fd,
249 (struct linux_dirent64 *)buffer,
250 sizeof(buffer))) > 0) {
251 struct linux_dirent64 *entry;
252 int offset;
253 for (offset = 0; offset < bytes; offset += entry->d_reclen) {
254 int fd;
255 entry = (struct linux_dirent64 *)(buffer + offset);
256 if ((fd = _pos_int_from_ascii(entry->d_name)) < 0)
257 continue; /* Not a number. */
258 if (fd != fd_dir_fd && fd >= start_fd && fd < end_fd &&
259 !_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) {
260 while (close(fd) < 0 && errno == EINTR);
261 }
262 }
263 }
264 close(fd_dir_fd);
265 }
266 }
267
268 #define _close_open_fd_range _close_open_fd_range_safe
269
270 #else /* NOT (defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)) */
271
272
273 /* Close all open file descriptors in the range start_fd inclusive to end_fd
274 * exclusive. Do not close any in the sorted py_fds_to_keep list.
275 *
276 * This function violates the strict use of async signal safe functions. :(
277 * It calls opendir(), readdir() and closedir(). Of these, the one most
278 * likely to ever cause a problem is opendir() as it performs an internal
279 * malloc(). Practically this should not be a problem. The Java VM makes the
280 * same calls between fork and exec in its own UNIXProcess_md.c implementation.
281 *
282 * readdir_r() is not used because it provides no benefit. It is typically
283 * implemented as readdir() followed by memcpy(). See also:
284 * http://womble.decadent.org.uk/readdir_r-advisory.html
285 */
286 static void
287 _close_open_fd_range_maybe_unsafe(int start_fd, int end_fd,
288 PyObject* py_fds_to_keep)
289 {
290 DIR *proc_fd_dir;
291 #ifndef HAVE_DIRFD
292 while (_is_fd_in_sorted_fd_sequence(start_fd, py_fds_to_keep) &&
293 (start_fd < end_fd)) {
294 ++start_fd;
295 }
296 if (start_fd >= end_fd)
297 return;
298 /* Close our lowest fd before we call opendir so that it is likely to
299 * reuse that fd otherwise we might close opendir's file descriptor in
300 * our loop. This trick assumes that fd's are allocated on a lowest
301 * available basis. */
302 while (close(start_fd) < 0 && errno == EINTR);
303 ++start_fd;
304 #endif
305 if (start_fd >= end_fd)
306 return;
307
308 #if defined(__FreeBSD__)
309 if (!_is_fdescfs_mounted_on_dev_fd())
310 proc_fd_dir = NULL;
311 else
312 #endif
313 proc_fd_dir = opendir(FD_DIR);
314 if (!proc_fd_dir) {
315 /* No way to get a list of open fds. */
316 _close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep);
317 } else {
318 struct dirent *dir_entry;
319 #ifdef HAVE_DIRFD
320 int fd_used_by_opendir = dirfd(proc_fd_dir);
321 #else
322 int fd_used_by_opendir = start_fd - 1;
323 #endif
324 errno = 0;
325 while ((dir_entry = readdir(proc_fd_dir))) {
326 int fd;
327 if ((fd = _pos_int_from_ascii(dir_entry->d_name)) < 0)
328 continue; /* Not a number. */
329 if (fd != fd_used_by_opendir && fd >= start_fd && fd < end_fd &&
330 !_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) {
331 while (close(fd) < 0 && errno == EINTR);
332 }
333 errno = 0;
334 }
335 if (errno) {
336 /* readdir error, revert behavior. Highly Unlikely. */
337 _close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep);
338 }
339 closedir(proc_fd_dir);
340 }
341 }
342
343 #define _close_open_fd_range _close_open_fd_range_maybe_unsafe
344
345 #endif /* else NOT (defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)) */
346
347
348 /*
349 * This function is code executed in the child process immediately after fork
350 * to set things up and call exec().
351 *
352 * All of the code in this function must only use async-signal-safe functions,
353 * listed at `man 7 signal` or
354 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
355 *
356 * This restriction is documented at
357 * http://www.opengroup.org/onlinepubs/009695399/functions/fork.html.
358 */
359 static void
360 child_exec(char *const exec_array[],
361 char *const argv[],
362 char *const envp[],
363 const char *cwd,
364 int p2cread, int p2cwrite,
365 int c2pread, int c2pwrite,
366 int errread, int errwrite,
367 int errpipe_read, int errpipe_write,
368 int close_fds, int restore_signals,
369 int call_setsid,
370 PyObject *py_fds_to_keep,
371 PyObject *preexec_fn,
372 PyObject *preexec_fn_args_tuple)
373 {
374 int i, saved_errno, unused, reached_preexec = 0;
375 PyObject *result;
376 const char* err_msg = "";
377 /* Buffer large enough to hold a hex integer. We can't malloc. */
378 char hex_errno[sizeof(saved_errno)*2+1];
379
380 /* Close parent's pipe ends. */
381 if (p2cwrite != -1) {
382 POSIX_CALL(close(p2cwrite));
383 }
384 if (c2pread != -1) {
385 POSIX_CALL(close(c2pread));
386 }
387 if (errread != -1) {
388 POSIX_CALL(close(errread));
389 }
390 POSIX_CALL(close(errpipe_read));
391
392 /* When duping fds, if there arises a situation where one of the fds is
393 either 0, 1 or 2, it is possible that it is overwritten (#12607). */
394 if (c2pwrite == 0)
395 POSIX_CALL(c2pwrite = dup(c2pwrite));
396 if (errwrite == 0 || errwrite == 1)
397 POSIX_CALL(errwrite = dup(errwrite));
398
399 /* Dup fds for child.
400 dup2() removes the CLOEXEC flag but we must do it ourselves if dup2()
401 would be a no-op (issue #10806). */
402 if (p2cread == 0) {
403 int old = fcntl(p2cread, F_GETFD);
404 if (old != -1)
405 fcntl(p2cread, F_SETFD, old & ~FD_CLOEXEC);
406 } else if (p2cread != -1) {
407 POSIX_CALL(dup2(p2cread, 0)); /* stdin */
408 }
409 if (c2pwrite == 1) {
410 int old = fcntl(c2pwrite, F_GETFD);
411 if (old != -1)
412 fcntl(c2pwrite, F_SETFD, old & ~FD_CLOEXEC);
413 } else if (c2pwrite != -1) {
414 POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */
415 }
416 if (errwrite == 2) {
417 int old = fcntl(errwrite, F_GETFD);
418 if (old != -1)
419 fcntl(errwrite, F_SETFD, old & ~FD_CLOEXEC);
420 } else if (errwrite != -1) {
421 POSIX_CALL(dup2(errwrite, 2)); /* stderr */
422 }
423
424 /* Close pipe fds. Make sure we don't close the same fd more than */
425 /* once, or standard fds. */
426 if (p2cread > 2) {
427 POSIX_CALL(close(p2cread));
428 }
429 if (c2pwrite > 2 && c2pwrite != p2cread) {
430 POSIX_CALL(close(c2pwrite));
431 }
432 if (errwrite != c2pwrite && errwrite != p2cread && errwrite > 2) {
433 POSIX_CALL(close(errwrite));
434 }
435
436 if (cwd)
437 POSIX_CALL(chdir(cwd));
438
439 if (restore_signals)
440 _Py_RestoreSignals();
441
442 #ifdef HAVE_SETSID
443 if (call_setsid)
444 POSIX_CALL(setsid());
445 #endif
446
447 reached_preexec = 1;
448 if (preexec_fn != Py_None && preexec_fn_args_tuple) {
449 /* This is where the user has asked us to deadlock their program. */
450 result = PyObject_Call(preexec_fn, preexec_fn_args_tuple, NULL);
451 if (result == NULL) {
452 /* Stringifying the exception or traceback would involve
453 * memory allocation and thus potential for deadlock.
454 * We've already faced potential deadlock by calling back
455 * into Python in the first place, so it probably doesn't
456 * matter but we avoid it to minimize the possibility. */
457 err_msg = "Exception occurred in preexec_fn.";
458 errno = 0; /* We don't want to report an OSError. */
459 goto error;
460 }
461 /* Py_DECREF(result); - We're about to exec so why bother? */
462 }
463
464 if (close_fds) {
465 int local_max_fd = max_fd;
466 #if defined(__NetBSD__)
467 local_max_fd = fcntl(0, F_MAXFD);
468 if (local_max_fd < 0)
469 local_max_fd = max_fd;
470 #endif
471 /* TODO HP-UX could use pstat_getproc() if anyone cares about it. */
472 _close_open_fd_range(3, local_max_fd, py_fds_to_keep);
473 }
474
475 /* This loop matches the Lib/os.py _execvpe()'s PATH search when */
476 /* given the executable_list generated by Lib/subprocess.py. */
477 saved_errno = 0;
478 for (i = 0; exec_array[i] != NULL; ++i) {
479 const char *executable = exec_array[i];
480 if (envp) {
481 execve(executable, argv, envp);
482 } else {
483 execv(executable, argv);
484 }
485 if (errno != ENOENT && errno != ENOTDIR && saved_errno == 0) {
486 saved_errno = errno;
487 }
488 }
489 /* Report the first exec error, not the last. */
490 if (saved_errno)
491 errno = saved_errno;
492
493 error:
494 saved_errno = errno;
495 /* Report the posix error to our parent process. */
496 /* We ignore all write() return values as the total size of our writes is
497 * less than PIPEBUF and we cannot do anything about an error anyways. */
498 if (saved_errno) {
499 char *cur;
500 unused = write(errpipe_write, "OSError:", 8);
501 cur = hex_errno + sizeof(hex_errno);
502 while (saved_errno != 0 && cur > hex_errno) {
503 *--cur = "0123456789ABCDEF"[saved_errno % 16];
504 saved_errno /= 16;
505 }
506 unused = write(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur);
507 unused = write(errpipe_write, ":", 1);
508 if (!reached_preexec) {
509 /* Indicate to the parent that the error happened before exec(). */
510 unused = write(errpipe_write, "noexec", 6);
511 }
512 /* We can't call strerror(saved_errno). It is not async signal safe.
513 * The parent process will look the error message up. */
514 } else {
515 unused = write(errpipe_write, "RuntimeError:0:", 15);
516 unused = write(errpipe_write, err_msg, strlen(err_msg));
517 }
518 if (unused) return; /* silly? yes! avoids gcc compiler warning. */
519 }
520
521
522 static PyObject *
523 subprocess_fork_exec(PyObject* self, PyObject *args)
524 {
525 PyObject *gc_module = NULL;
526 PyObject *executable_list, *py_close_fds, *py_fds_to_keep;
527 PyObject *env_list, *preexec_fn;
528 PyObject *process_args, *converted_args = NULL, *fast_args = NULL;
529 PyObject *preexec_fn_args_tuple = NULL;
530 int p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite;
531 int errpipe_read, errpipe_write, close_fds, restore_signals;
532 int call_setsid;
533 PyObject *cwd_obj, *cwd_obj2;
534 const char *cwd;
535 pid_t pid;
536 int need_to_reenable_gc = 0;
537 char *const *exec_array, *const *argv = NULL, *const *envp = NULL;
538 Py_ssize_t arg_num;
539
540 if (!PyArg_ParseTuple(
541 args, "OOOOOOiiiiiiiiiiO:fork_exec",
542 &process_args, &executable_list, &py_close_fds, &py_fds_to_keep,
543 &cwd_obj, &env_list,
544 &p2cread, &p2cwrite, &c2pread, &c2pwrite,
545 &errread, &errwrite, &errpipe_read, &errpipe_write,
546 &restore_signals, &call_setsid, &preexec_fn))
547 return NULL;
548
549 close_fds = PyObject_IsTrue(py_close_fds);
550 if (close_fds < 0)
551 return NULL;
552 if (close_fds && errpipe_write < 3) { /* precondition */
553 PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3");
554 return NULL;
555 }
556 if (PySequence_Length(py_fds_to_keep) < 0) {
557 PyErr_SetString(PyExc_ValueError, "cannot get length of fds_to_keep");
558 return NULL;
559 }
560 if (_sanity_check_python_fd_sequence(py_fds_to_keep)) {
561 PyErr_SetString(PyExc_ValueError, "bad value(s) in fds_to_keep");
562 return NULL;
563 }
564
565 /* We need to call gc.disable() when we'll be calling preexec_fn */
566 if (preexec_fn != Py_None) {
567 PyObject *result;
568 gc_module = PyImport_ImportModule("gc");
569 if (gc_module == NULL)
570 return NULL;
571 result = PyObject_CallMethod(gc_module, "isenabled", NULL);
572 if (result == NULL) {
573 Py_DECREF(gc_module);
574 return NULL;
575 }
576 need_to_reenable_gc = PyObject_IsTrue(result);
577 Py_DECREF(result);
578 if (need_to_reenable_gc == -1) {
579 Py_DECREF(gc_module);
580 return NULL;
581 }
582 result = PyObject_CallMethod(gc_module, "disable", NULL);
583 if (result == NULL) {
584 Py_DECREF(gc_module);
585 return NULL;
586 }
587 Py_DECREF(result);
588 }
589
590 exec_array = _PySequence_BytesToCharpArray(executable_list);
591 if (!exec_array) {
592 Py_XDECREF(gc_module);
593 return NULL;
594 }
595
596 /* Convert args and env into appropriate arguments for exec() */
597 /* These conversions are done in the parent process to avoid allocating
598 or freeing memory in the child process. */
599 if (process_args != Py_None) {
600 Py_ssize_t num_args;
601 /* Equivalent to: */
602 /* tuple(PyUnicode_FSConverter(arg) for arg in process_args) */
603 fast_args = PySequence_Fast(process_args, "argv must be a tuple");
604 if (fast_args == NULL)
605 goto cleanup;
606 num_args = PySequence_Fast_GET_SIZE(fast_args);
607 converted_args = PyTuple_New(num_args);
608 if (converted_args == NULL)
609 goto cleanup;
610 for (arg_num = 0; arg_num < num_args; ++arg_num) {
611 PyObject *borrowed_arg, *converted_arg;
612 borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num);
613 if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0)
614 goto cleanup;
615 PyTuple_SET_ITEM(converted_args, arg_num, converted_arg);
616 }
617
618 argv = _PySequence_BytesToCharpArray(converted_args);
619 Py_CLEAR(converted_args);
620 Py_CLEAR(fast_args);
621 if (!argv)
622 goto cleanup;
623 }
624
625 if (env_list != Py_None) {
626 envp = _PySequence_BytesToCharpArray(env_list);
627 if (!envp)
628 goto cleanup;
629 }
630
631 if (preexec_fn != Py_None) {
632 preexec_fn_args_tuple = PyTuple_New(0);
633 if (!preexec_fn_args_tuple)
634 goto cleanup;
635 _PyImport_AcquireLock();
636 }
637
638 if (cwd_obj != Py_None) {
639 if (PyUnicode_FSConverter(cwd_obj, &cwd_obj2) == 0)
640 goto cleanup;
641 cwd = PyString_AsString(cwd_obj2);
642 } else {
643 cwd = NULL;
644 cwd_obj2 = NULL;
645 }
646
647 pid = fork();
648 if (pid == 0) {
649 /* Child process */
650 /*
651 * Code from here to _exit() must only use async-signal-safe functions,
652 * listed at `man 7 signal` or
653 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04 .html.
654 */
655
656 if (preexec_fn != Py_None) {
657 /* We'll be calling back into Python later so we need to do this.
658 * This call may not be async-signal-safe but neither is calling
659 * back into Python. The user asked us to use hope as a strategy
660 * to avoid deadlock... */
661 PyOS_AfterFork();
662 }
663
664 child_exec(exec_array, argv, envp, cwd,
665 p2cread, p2cwrite, c2pread, c2pwrite,
666 errread, errwrite, errpipe_read, errpipe_write,
667 close_fds, restore_signals, call_setsid,
668 py_fds_to_keep, preexec_fn, preexec_fn_args_tuple);
669 _exit(255);
670 return NULL; /* Dead code to avoid a potential compiler warning. */
671 }
672 Py_XDECREF(cwd_obj2);
673
674 if (pid == -1) {
675 /* Capture the errno exception before errno can be clobbered. */
676 PyErr_SetFromErrno(PyExc_OSError);
677 }
678 if (preexec_fn != Py_None &&
679 _PyImport_ReleaseLock() < 0 && !PyErr_Occurred()) {
680 PyErr_SetString(PyExc_RuntimeError,
681 "not holding the import lock");
682 }
683
684 /* Parent process */
685 if (envp)
686 _Py_FreeCharPArray(envp);
687 if (argv)
688 _Py_FreeCharPArray(argv);
689 _Py_FreeCharPArray(exec_array);
690
691 /* Reenable gc in the parent process (or if fork failed). */
692 if (need_to_reenable_gc && _enable_gc(gc_module)) {
693 Py_XDECREF(gc_module);
694 return NULL;
695 }
696 Py_XDECREF(preexec_fn_args_tuple);
697 Py_XDECREF(gc_module);
698
699 if (pid == -1)
700 return NULL; /* fork() failed. Exception set earlier. */
701
702 return PyLong_FromPid(pid);
703
704 cleanup:
705 if (envp)
706 _Py_FreeCharPArray(envp);
707 if (argv)
708 _Py_FreeCharPArray(argv);
709 _Py_FreeCharPArray(exec_array);
710 Py_XDECREF(converted_args);
711 Py_XDECREF(fast_args);
712 Py_XDECREF(preexec_fn_args_tuple);
713
714 /* Reenable gc if it was disabled. */
715 if (need_to_reenable_gc)
716 _enable_gc(gc_module);
717 Py_XDECREF(gc_module);
718 return NULL;
719 }
720
721
722 PyDoc_STRVAR(subprocess_fork_exec_doc,
723 "fork_exec(args, executable_list, close_fds, cwd, env,\n\
724 p2cread, p2cwrite, c2pread, c2pwrite,\n\
725 errread, errwrite, errpipe_read, errpipe_write,\n\
726 restore_signals, call_setsid, preexec_fn)\n\
727 \n\
728 Forks a child process, closes parent file descriptors as appropriate in the\n\
729 child and dups the few that are needed before calling exec() in the child\n\
730 process.\n\
731 \n\
732 The preexec_fn, if supplied, will be called immediately before exec.\n\
733 WARNING: preexec_fn is NOT SAFE if your application uses threads.\n\
734 It may trigger infrequent, difficult to debug deadlocks.\n\
735 \n\
736 If an error occurs in the child process before the exec, it is\n\
737 serialized and written to the errpipe_write fd per subprocess.py.\n\
738 \n\
739 Returns: the child process's PID.\n\
740 \n\
741 Raises: Only on an error in the parent process.\n\
742 ");
743
744 PyDoc_STRVAR(subprocess_cloexec_pipe_doc,
745 "cloexec_pipe() -> (read_end, write_end)\n\n\
746 Create a pipe whose ends have the cloexec flag set; write_end will be >= 3.");
747
748 static PyObject *
749 subprocess_cloexec_pipe(PyObject *self, PyObject *noargs)
750 {
751 int fds[2];
752 int res, saved_errno;
753 long oldflags;
754 #ifdef HAVE_PIPE2
755 Py_BEGIN_ALLOW_THREADS
756 res = pipe2(fds, O_CLOEXEC);
757 Py_END_ALLOW_THREADS
758 if (res != 0 && errno == ENOSYS)
759 {
760 #endif
761 /* We hold the GIL which offers some protection from other code calling
762 * fork() before the CLOEXEC flags have been set but we can't guarantee
763 * anything without pipe2(). */
764 res = pipe(fds);
765
766 if (res == 0) {
767 oldflags = fcntl(fds[0], F_GETFD, 0);
768 if (oldflags < 0) res = oldflags;
769 }
770 if (res == 0)
771 res = fcntl(fds[0], F_SETFD, oldflags | FD_CLOEXEC);
772
773 if (res == 0) {
774 oldflags = fcntl(fds[1], F_GETFD, 0);
775 if (oldflags < 0) res = oldflags;
776 }
777 if (res == 0)
778 res = fcntl(fds[1], F_SETFD, oldflags | FD_CLOEXEC);
779 #ifdef HAVE_PIPE2
780 }
781 #endif
782 if (res == 0 && fds[1] < 3) {
783 /* We always want the write end of the pipe to avoid fds 0, 1 and 2
784 * as our child may claim those for stdio connections. */
785 int write_fd = fds[1];
786 int fds_to_close[3] = {-1, -1, -1};
787 int fds_to_close_idx = 0;
788 #ifdef F_DUPFD_CLOEXEC
789 fds_to_close[fds_to_close_idx++] = write_fd;
790 write_fd = fcntl(write_fd, F_DUPFD_CLOEXEC, 3);
791 if (write_fd < 0) /* We don't support F_DUPFD_CLOEXEC / other error */
792 #endif
793 {
794 /* Use dup a few times until we get a desirable fd. */
795 for (; fds_to_close_idx < 3; ++fds_to_close_idx) {
796 fds_to_close[fds_to_close_idx] = write_fd;
797 write_fd = dup(write_fd);
798 if (write_fd >= 3)
799 break;
800 /* We may dup a few extra times if it returns an error but
801 * that is okay. Repeat calls should return the same error. */
802 }
803 if (write_fd < 0) res = write_fd;
804 if (res == 0) {
805 oldflags = fcntl(write_fd, F_GETFD, 0);
806 if (oldflags < 0) res = oldflags;
807 if (res == 0)
808 res = fcntl(write_fd, F_SETFD, oldflags | FD_CLOEXEC);
809 }
810 }
811 saved_errno = errno;
812 /* Close fds we tried for the write end that were too low. */
813 for (fds_to_close_idx=0; fds_to_close_idx < 3; ++fds_to_close_idx) {
814 int temp_fd = fds_to_close[fds_to_close_idx];
815 while (temp_fd >= 0 && close(temp_fd) < 0 && errno == EINTR);
816 }
817 errno = saved_errno; /* report dup or fcntl errors, not close. */
818 fds[1] = write_fd;
819 } /* end if write fd was too small */
820
821 if (res != 0)
822 return PyErr_SetFromErrno(PyExc_OSError);
823 return Py_BuildValue("(ii)", fds[0], fds[1]);
824 }
825
826 /* module level code ********************************************************/
827
828 #define MIN_PY_VERSION_WITH_PYIMPORT_ACQUIRELOCK 0x02060300
829 #if (PY_VERSION_HEX < MIN_PY_VERSION_WITH_PYIMPORT_ACQUIRELOCK)
830 static PyObject* imp_module;
831
832 static void
833 _PyImport_AcquireLock(void)
834 {
835 PyObject *result;
836 result = PyObject_CallMethod(imp_module, "acquire_lock", NULL);
837 if (result == NULL) {
838 fprintf(stderr, "imp.acquire_lock() failed.\n");
839 return;
840 }
841 Py_DECREF(result);
842 }
843
844 static int
845 _PyImport_ReleaseLock(void)
846 {
847 PyObject *result;
848 result = PyObject_CallMethod(imp_module, "release_lock", NULL);
849 if (result == NULL) {
850 fprintf(stderr, "imp.release_lock() failed.\n");
851 return -1;
852 }
853 Py_DECREF(result);
854 return 0;
855 }
856 #endif /* Python <= 2.5 */
857
858
859 PyDoc_STRVAR(module_doc,
860 "A POSIX helper for the subprocess module.");
861
862
863 static PyMethodDef module_methods[] = {
864 {"fork_exec", subprocess_fork_exec, METH_VARARGS, subprocess_fork_exec_doc},
865 {"cloexec_pipe", subprocess_cloexec_pipe, METH_NOARGS, subprocess_cloexec_pi pe_doc},
866 {NULL, NULL} /* sentinel */
867 };
868
869
870 PyMODINIT_FUNC
871 init_posixsubprocess(void)
872 {
873 PyObject *m;
874
875 #ifdef _SC_OPEN_MAX
876 max_fd = sysconf(_SC_OPEN_MAX);
877 if (max_fd == -1)
878 #endif
879 max_fd = 256; /* Matches Lib/subprocess.py */
880
881 #if (PY_VERSION_HEX < MIN_PY_VERSION_WITH_PYIMPORT_ACQUIRELOCK)
882 imp_module = PyImport_ImportModule("imp");
883 if (imp_module == NULL)
884 return;
885 #endif
886
887 m = Py_InitModule3("_posixsubprocess", module_methods, module_doc);
888 if (m == NULL)
889 return;
890 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698