set close-on-exec in pipe size modification check
authorEric Wong <normalperson@yhbt.net>
Sun, 21 Apr 2013 03:22:26 +0000 (21 03:22 +0000)
committerEric Wong <normalperson@yhbt.net>
Sun, 21 Apr 2013 03:26:29 +0000 (21 03:26 +0000)
This prevents a file descriptor leak in case another thread
forks and execs while we are in the middle of loading.  This
places a hard dependency on pipe2, but pipe2 appeared in Linux
before pipe size modification.

ext/io_splice/extconf.rb
ext/io_splice/io_splice_ext.c

index 27127c8..52dab83 100644 (file)
@@ -3,6 +3,7 @@ $CPPFLAGS << ' -D_GNU_SOURCE=1'
 
 have_func('splice', %w(fcntl.h)) or abort 'splice(2) not defined'
 have_func('tee', %w(fcntl.h)) or abort 'tee(2) not defined'
+have_func('pipe2', %w(fcntl.h unistd.h))
 have_func('rb_thread_blocking_region')
 have_macro('F_GETPIPE_SZ', %w(fcntl.h))
 have_macro('F_SETPIPE_SZ', %w(fcntl.h))
index e429266..1c938c3 100644 (file)
@@ -619,8 +619,14 @@ static VALUE set_pipe_size(VALUE self, VALUE size)
 
 static int can_mod_pipe_size(void)
 {
+       /*
+        * pipe2 appeared in Linux 2.6.27, F_*PIPE_SZ appeared in 2.6.35,
+        * thus not having pipe2 automatically disqualifies us from having
+        * F_*PIPE_SZ support
+        */
+#ifdef HAVE_PIPE2
        int fds[2];
-       int rc = pipe(fds);
+       int rc = pipe2(fds, O_CLOEXEC);
 
        if (rc == 0) {
                rc = fcntl(fds[0], F_GETPIPE_SZ);
@@ -629,11 +635,17 @@ static int can_mod_pipe_size(void)
                (void)close(fds[0]);
                (void)close(fds[1]);
        } else {
-               /* weird error, but don't raise during init */
+               /*
+                * weird error, but don't raise during init, this could be
+                * ENOSYS, even..
+                */
                rc = 0;
        }
        errno = 0;
        return rc;
+#else  /* ! HAVE_PIPE2 */
+       return 0;
+#endif /* ! HAVE_PIPE2 */
 }
 
 void Init_io_splice_ext(void)