about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-04-21 03:22:26 +0000
committerEric Wong <normalperson@yhbt.net>2013-04-21 03:26:29 +0000
commitb9979f380f1dc8bbde89c16b0fa25a67f9bc1830 (patch)
treec3b3941fd14c0dffc3702aff7c99bd84e208618c
parentb24af7d357644bfe5c65785d58492845b00e888d (diff)
downloadruby_io_splice-b9979f380f1dc8bbde89c16b0fa25a67f9bc1830.tar.gz
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.
-rw-r--r--ext/io_splice/extconf.rb1
-rw-r--r--ext/io_splice/io_splice_ext.c16
2 files changed, 15 insertions, 2 deletions
diff --git a/ext/io_splice/extconf.rb b/ext/io_splice/extconf.rb
index 27127c8..52dab83 100644
--- a/ext/io_splice/extconf.rb
+++ b/ext/io_splice/extconf.rb
@@ -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))
diff --git a/ext/io_splice/io_splice_ext.c b/ext/io_splice/io_splice_ext.c
index e429266..1c938c3 100644
--- a/ext/io_splice/io_splice_ext.c
+++ b/ext/io_splice/io_splice_ext.c
@@ -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)