Project

General

Profile

Misc #14907 ยป 0001-io.c-do-not-close-inherited-FDs-by-default.patch

normalperson (Eric Wong), 07/11/2018 10:33 AM

View differences:

io.c
181 181
    int8_t init_p, next_p, binmode;
182 182
};
183 183

  
184
static rb_atomic_t max_file_descriptor = NOFILE;
185 184
void
186 185
rb_update_max_fd(int fd)
187 186
{
188
    struct stat buf;
189
    rb_atomic_t afd = (rb_atomic_t)fd;
190
    rb_atomic_t max_fd = max_file_descriptor;
191

  
192
    if (afd <= max_fd)
193
        return;
194

  
195
    if (fstat(fd, &buf) != 0 && errno == EBADF) {
196
        rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
197
    }
198

  
199
    while (max_fd < afd) {
200
	max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
201
    }
187
    /* noop */
202 188
}
203 189

  
204 190
void
......
6332 6318
    }
6333 6319
}
6334 6320

  
6335
#if defined(__linux__)
6336
/* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
6337
 * Since /proc may not be available, linux_get_maxfd is just a hint.
6338
 * This function, linux_get_maxfd, must be async-signal-safe.
6339
 * I.e. opendir() is not usable.
6340
 *
6341
 * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
6342
 * However they are easy to re-implement in async-signal-safe manner.
6343
 * (Also note that there is missing/memcmp.c.)
6344
 */
6345
static int
6346
linux_get_maxfd(void)
6347
{
6348
    int fd;
6349
    char buf[4096], *p, *np, *e;
6350
    ssize_t ss;
6351
    fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
6352
    if (fd == -1) return -1;
6353
    ss = read(fd, buf, sizeof(buf));
6354
    if (ss == -1) goto err;
6355
    p = buf;
6356
    e = buf + ss;
6357
    while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
6358
           (np = memchr(p, '\n', e-p)) != NULL) {
6359
        if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
6360
            int fdsize;
6361
            p += sizeof("FDSize:")-1;
6362
            *np = '\0';
6363
            fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
6364
            close(fd);
6365
            return fdsize;
6366
        }
6367
        p = np+1;
6368
    }
6369
    /* fall through */
6370

  
6371
  err:
6372
    close(fd);
6373
    return -1;
6374
}
6375
#endif
6376

  
6377 6321
/* This function should be async-signal-safe. */
6378 6322
void
6379 6323
rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
6380 6324
{
6381
#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6382
    int fd, ret;
6383
    int max = (int)max_file_descriptor;
6384
# ifdef F_MAXFD
6385
    /* F_MAXFD is available since NetBSD 2.0. */
6386
    ret = fcntl(0, F_MAXFD); /* async-signal-safe */
6387
    if (ret != -1)
6388
        maxhint = max = ret;
6389
# elif defined(__linux__)
6390
    ret = linux_get_maxfd();
6391
    if (maxhint < ret)
6392
        maxhint = ret;
6393
    /* maxhint = max = ret; if (ret == -1) abort(); // test */
6394
# endif
6395
    if (max < maxhint)
6396
        max = maxhint;
6397
    for (fd = lowfd; fd <= max; fd++) {
6398
        if (!NIL_P(noclose_fds) &&
6399
            RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
6400
            continue;
6401
	ret = fcntl(fd, F_GETFD); /* async-signal-safe */
6402
	if (ret != -1 && !(ret & FD_CLOEXEC)) {
6403
            fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
6404
        }
6405
# define CONTIGUOUS_CLOSED_FDS 20
6406
        if (ret != -1) {
6407
	    if (max < fd + CONTIGUOUS_CLOSED_FDS)
6408
		max = fd + CONTIGUOUS_CLOSED_FDS;
6409
	}
6410
    }
6411
#endif
6325
    /* no-op */
6412 6326
}
6413 6327

  
6414 6328
static int
test/lib/test/unit.rb
145 145
            r.close if r
146 146
            nil
147 147
          else
148
            r.close_on_exec = true
149
            r.close_on_exec = true
148 150
            @jobserver = [r, w]
149 151
            options[:parallel] ||= 1
150 152
          end
151
-