58
/* Convert ASCII to a positive int, no libc call. no overflow. -1 on error. */
60
_pos_int_from_ascii(char *name)
63
while (*name >= '0' && *name <= '9') {
64
num = num * 10 + (*name - '0');
68
return -1; /* Non digit found, not a number. */
73
#if defined(__FreeBSD__)
74
/* When /dev/fd isn't mounted it is often a static directory populated
75
* with 0 1 2 or entries for 0 .. 63 on FreeBSD, NetBSD and OpenBSD.
76
* NetBSD and OpenBSD have a /proc fs available (though not necessarily
77
* mounted) and do not have fdescfs for /dev/fd. MacOS X has a devfs
78
* that properly supports /dev/fd.
81
_is_fdescfs_mounted_on_dev_fd()
84
struct stat dev_fd_stat;
85
if (stat("/dev", &dev_stat) != 0)
87
if (stat(FD_DIR, &dev_fd_stat) != 0)
89
if (dev_stat.st_dev == dev_fd_stat.st_dev)
90
return 0; /* / == /dev == /dev/fd means it is static. #fail */
96
/* Returns 1 if there is a problem with fd_sequence, 0 otherwise. */
98
_sanity_check_python_fd_sequence(PyObject *fd_sequence)
100
Py_ssize_t seq_idx, seq_len = PySequence_Length(fd_sequence);
102
for (seq_idx = 0; seq_idx < seq_len; ++seq_idx) {
103
PyObject* py_fd = PySequence_Fast_GET_ITEM(fd_sequence, seq_idx);
104
long iter_fd = PyLong_AsLong(py_fd);
105
if (iter_fd < 0 || iter_fd < prev_fd || iter_fd > INT_MAX) {
106
/* Negative, overflow, not a Long, unsorted, too big for a fd. */
114
/* Is fd found in the sorted Python Sequence? */
116
_is_fd_in_sorted_fd_sequence(int fd, PyObject *fd_sequence)
119
Py_ssize_t search_min = 0;
120
Py_ssize_t search_max = PySequence_Length(fd_sequence) - 1;
124
long middle = (search_min + search_max) / 2;
125
long middle_fd = PyLong_AsLong(
126
PySequence_Fast_GET_ITEM(fd_sequence, middle));
130
search_min = middle + 1;
132
search_max = middle - 1;
133
} while (search_min <= search_max);
138
/* Close all file descriptors in the range start_fd inclusive to
139
* end_fd exclusive except for those in py_fds_to_keep. If the
140
* range defined by [start_fd, end_fd) is large this will take a
141
* long time as it calls close() on EVERY possible fd.
144
_close_fds_by_brute_force(int start_fd, int end_fd, PyObject *py_fds_to_keep)
146
Py_ssize_t num_fds_to_keep = PySequence_Length(py_fds_to_keep);
147
Py_ssize_t keep_seq_idx;
149
/* As py_fds_to_keep is sorted we can loop through the list closing
150
* fds inbetween any in the keep list falling within our range. */
151
for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
152
PyObject* py_keep_fd = PySequence_Fast_GET_ITEM(py_fds_to_keep,
154
int keep_fd = PyLong_AsLong(py_keep_fd);
155
if (keep_fd < start_fd)
157
for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) {
158
while (close(fd_num) < 0 && errno == EINTR);
160
start_fd = keep_fd + 1;
162
if (start_fd <= end_fd) {
163
for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
164
while (close(fd_num) < 0 && errno == EINTR);
170
#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
171
/* It doesn't matter if d_name has room for NAME_MAX chars; we're using this
172
* only to read a directory of short file descriptor number names. The kernel
173
* will return an error if we didn't give it enough space. Highly Unlikely.
174
* This structure is very old and stable: It will not change unless the kernel
175
* chooses to break compatibility with all existing binaries. Highly Unlikely.
177
struct linux_dirent {
178
unsigned long d_ino; /* Inode number */
179
unsigned long d_off; /* Offset to next linux_dirent */
180
unsigned short d_reclen; /* Length of this linux_dirent */
181
char d_name[256]; /* Filename (null-terminated) */
184
/* Close all open file descriptors in the range start_fd inclusive to end_fd
185
* exclusive. Do not close any in the sorted py_fds_to_keep list.
187
* This version is async signal safe as it does not make any unsafe C library
188
* calls, malloc calls or handle any locks. It is _unfortunate_ to be forced
189
* to resort to making a kernel system call directly but this is the ONLY api
190
* available that does no harm. opendir/readdir/closedir perform memory
191
* allocation and locking so while they usually work they are not guaranteed
192
* to (especially if you have replaced your malloc implementation). A version
193
* of this function that uses those can be found in the _maybe_unsafe variant.
195
* This is Linux specific because that is all I am ready to test it on. It
196
* should be easy to add OS specific dirent or dirent64 structures and modify
197
* it with some cpp #define magic to work on other OSes as well if you want.
200
_close_open_fd_range_safe(int start_fd, int end_fd, PyObject* py_fds_to_keep)
203
if (start_fd >= end_fd)
205
fd_dir_fd = open(FD_DIR, O_RDONLY | O_CLOEXEC, 0);
206
if (fd_dir_fd == -1) {
207
/* No way to get a list of open fds. */
208
_close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep);
211
char buffer[sizeof(struct linux_dirent)];
213
while ((bytes = syscall(SYS_getdents, fd_dir_fd,
214
(struct linux_dirent *)buffer,
215
sizeof(buffer))) > 0) {
216
struct linux_dirent *entry;
218
for (offset = 0; offset < bytes; offset += entry->d_reclen) {
220
entry = (struct linux_dirent *)(buffer + offset);
221
if ((fd = _pos_int_from_ascii(entry->d_name)) < 0)
222
continue; /* Not a number. */
223
if (fd != fd_dir_fd && fd >= start_fd && fd < end_fd &&
224
!_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) {
225
while (close(fd) < 0 && errno == EINTR);
233
#define _close_open_fd_range _close_open_fd_range_safe
235
#else /* NOT (defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)) */
238
/* Close all open file descriptors in the range start_fd inclusive to end_fd
239
* exclusive. Do not close any in the sorted py_fds_to_keep list.
241
* This function violates the strict use of async signal safe functions. :(
242
* It calls opendir(), readdir() and closedir(). Of these, the one most
243
* likely to ever cause a problem is opendir() as it performs an internal
244
* malloc(). Practically this should not be a problem. The Java VM makes the
245
* same calls between fork and exec in its own UNIXProcess_md.c implementation.
247
* readdir_r() is not used because it provides no benefit. It is typically
248
* implemented as readdir() followed by memcpy(). See also:
249
* http://womble.decadent.org.uk/readdir_r-advisory.html
252
_close_open_fd_range_maybe_unsafe(int start_fd, int end_fd,
253
PyObject* py_fds_to_keep)
257
while (_is_fd_in_sorted_fd_sequence(start_fd, py_fds_to_keep) &&
258
(start_fd < end_fd)) {
261
if (start_fd >= end_fd)
263
/* Close our lowest fd before we call opendir so that it is likely to
264
* reuse that fd otherwise we might close opendir's file descriptor in
265
* our loop. This trick assumes that fd's are allocated on a lowest
266
* available basis. */
267
while (close(start_fd) < 0 && errno == EINTR);
270
if (start_fd >= end_fd)
273
#if defined(__FreeBSD__)
274
if (!_is_fdescfs_mounted_on_dev_fd())
278
proc_fd_dir = opendir(FD_DIR);
280
/* No way to get a list of open fds. */
281
_close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep);
283
struct dirent *dir_entry;
285
int fd_used_by_opendir = dirfd(proc_fd_dir);
287
int fd_used_by_opendir = start_fd - 1;
290
while ((dir_entry = readdir(proc_fd_dir))) {
292
if ((fd = _pos_int_from_ascii(dir_entry->d_name)) < 0)
293
continue; /* Not a number. */
294
if (fd != fd_used_by_opendir && fd >= start_fd && fd < end_fd &&
295
!_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) {
296
while (close(fd) < 0 && errno == EINTR);
301
/* readdir error, revert behavior. Highly Unlikely. */
302
_close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep);
304
closedir(proc_fd_dir);
308
#define _close_open_fd_range _close_open_fd_range_maybe_unsafe
310
#endif /* else NOT (defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)) */
30
314
* This function is code executed in the child process immediately after fork
31
315
* to set things up and call exec().
37
321
* This restriction is documented at
38
322
* http://www.opengroup.org/onlinepubs/009695399/functions/fork.html.
40
static void child_exec(char *const exec_array[],
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,
49
int call_setsid, Py_ssize_t num_fds_to_keep,
50
PyObject *py_fds_to_keep,
52
PyObject *preexec_fn_args_tuple)
325
child_exec(char *const exec_array[],
329
int p2cread, int p2cwrite,
330
int c2pread, int c2pwrite,
331
int errread, int errwrite,
332
int errpipe_read, int errpipe_write,
333
int close_fds, int restore_signals,
335
PyObject *py_fds_to_keep,
336
PyObject *preexec_fn,
337
PyObject *preexec_fn_args_tuple)
54
int i, saved_errno, fd_num;
339
int i, saved_errno, unused;
56
341
const char* err_msg = "";
57
342
/* Buffer large enough to hold a hex integer. We can't malloc. */
190
458
saved_errno = errno;
191
459
/* Report the posix error to our parent process. */
460
/* We ignore all write() return values as the total size of our writes is
461
* less than PIPEBUF and we cannot do anything about an error anyways. */
192
462
if (saved_errno) {
194
write(errpipe_write, "OSError:", 8);
464
unused = write(errpipe_write, "OSError:", 8);
195
465
cur = hex_errno + sizeof(hex_errno);
196
466
while (saved_errno != 0 && cur > hex_errno) {
197
467
*--cur = "0123456789ABCDEF"[saved_errno % 16];
198
468
saved_errno /= 16;
200
write(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur);
201
write(errpipe_write, ":", 1);
470
unused = write(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur);
471
unused = write(errpipe_write, ":", 1);
202
472
/* We can't call strerror(saved_errno). It is not async signal safe.
203
473
* The parent process will look the error message up. */
205
write(errpipe_write, "RuntimeError:0:", 15);
206
write(errpipe_write, err_msg, strlen(err_msg));
475
unused = write(errpipe_write, "RuntimeError:0:", 15);
476
unused = write(errpipe_write, err_msg, strlen(err_msg));
478
if (unused) return; /* silly? yes! avoids gcc compiler warning. */