Misc #14907 » 0001-io.c-do-not-close-inherited-FDs-by-default.patch
| io.c | ||
|---|---|---|
|
int8_t init_p, next_p, binmode;
|
||
|
};
|
||
|
static rb_atomic_t max_file_descriptor = NOFILE;
|
||
|
void
|
||
|
rb_update_max_fd(int fd)
|
||
|
{
|
||
|
struct stat buf;
|
||
|
rb_atomic_t afd = (rb_atomic_t)fd;
|
||
|
rb_atomic_t max_fd = max_file_descriptor;
|
||
|
if (afd <= max_fd)
|
||
|
return;
|
||
|
if (fstat(fd, &buf) != 0 && errno == EBADF) {
|
||
|
rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
|
||
|
}
|
||
|
while (max_fd < afd) {
|
||
|
max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
|
||
|
}
|
||
|
/* noop */
|
||
|
}
|
||
|
void
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
#if defined(__linux__)
|
||
|
/* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
|
||
|
* Since /proc may not be available, linux_get_maxfd is just a hint.
|
||
|
* This function, linux_get_maxfd, must be async-signal-safe.
|
||
|
* I.e. opendir() is not usable.
|
||
|
*
|
||
|
* Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
|
||
|
* However they are easy to re-implement in async-signal-safe manner.
|
||
|
* (Also note that there is missing/memcmp.c.)
|
||
|
*/
|
||
|
static int
|
||
|
linux_get_maxfd(void)
|
||
|
{
|
||
|
int fd;
|
||
|
char buf[4096], *p, *np, *e;
|
||
|
ssize_t ss;
|
||
|
fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
|
||
|
if (fd == -1) return -1;
|
||
|
ss = read(fd, buf, sizeof(buf));
|
||
|
if (ss == -1) goto err;
|
||
|
p = buf;
|
||
|
e = buf + ss;
|
||
|
while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
|
||
|
(np = memchr(p, '\n', e-p)) != NULL) {
|
||
|
if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
|
||
|
int fdsize;
|
||
|
p += sizeof("FDSize:")-1;
|
||
|
*np = '\0';
|
||
|
fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
|
||
|
close(fd);
|
||
|
return fdsize;
|
||
|
}
|
||
|
p = np+1;
|
||
|
}
|
||
|
/* fall through */
|
||
|
err:
|
||
|
close(fd);
|
||
|
return -1;
|
||
|
}
|
||
|
#endif
|
||
|
/* This function should be async-signal-safe. */
|
||
|
void
|
||
|
rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
|
||
|
{
|
||
|
#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
|
||
|
int fd, ret;
|
||
|
int max = (int)max_file_descriptor;
|
||
|
# ifdef F_MAXFD
|
||
|
/* F_MAXFD is available since NetBSD 2.0. */
|
||
|
ret = fcntl(0, F_MAXFD); /* async-signal-safe */
|
||
|
if (ret != -1)
|
||
|
maxhint = max = ret;
|
||
|
# elif defined(__linux__)
|
||
|
ret = linux_get_maxfd();
|
||
|
if (maxhint < ret)
|
||
|
maxhint = ret;
|
||
|
/* maxhint = max = ret; if (ret == -1) abort(); // test */
|
||
|
# endif
|
||
|
if (max < maxhint)
|
||
|
max = maxhint;
|
||
|
for (fd = lowfd; fd <= max; fd++) {
|
||
|
if (!NIL_P(noclose_fds) &&
|
||
|
RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
|
||
|
continue;
|
||
|
ret = fcntl(fd, F_GETFD); /* async-signal-safe */
|
||
|
if (ret != -1 && !(ret & FD_CLOEXEC)) {
|
||
|
fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
|
||
|
}
|
||
|
# define CONTIGUOUS_CLOSED_FDS 20
|
||
|
if (ret != -1) {
|
||
|
if (max < fd + CONTIGUOUS_CLOSED_FDS)
|
||
|
max = fd + CONTIGUOUS_CLOSED_FDS;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
/* no-op */
|
||
|
}
|
||
|
static int
|
||
| test/lib/test/unit.rb | ||
|---|---|---|
|
r.close if r
|
||
|
nil
|
||
|
else
|
||
|
r.close_on_exec = true
|
||
|
r.close_on_exec = true
|
||
|
@jobserver = [r, w]
|
||
|
options[:parallel] ||= 1
|
||
|
end
|
||
|
-
|
||