diff options
author | Eric Wong <normalperson@yhbt.net> | 2011-03-21 10:57:30 -0700 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2011-03-21 10:57:30 -0700 |
commit | 877433494e4a848d6c6a10d0e6521061e6a10118 (patch) | |
tree | c4a78ca79dab08a6f2de3f81a574be1d8bfef946 | |
parent | a5d552d90942fe3c3d1adfc809638fd78992da6e (diff) | |
download | raindrops-877433494e4a848d6c6a10d0e6521061e6a10118.tar.gz |
Very few programs can take advantage of inheriting FDs across exec() boundaries, and inet_diag sockets have no reason to be used in this way.
-rw-r--r-- | ext/raindrops/linux_inet_diag.c | 21 | ||||
-rw-r--r-- | test/test_inet_diag_socket.rb | 3 |
2 files changed, 22 insertions, 2 deletions
diff --git a/ext/raindrops/linux_inet_diag.c b/ext/raindrops/linux_inet_diag.c index 7fef77c..7f9caaa 100644 --- a/ext/raindrops/linux_inet_diag.c +++ b/ext/raindrops/linux_inet_diag.c @@ -43,6 +43,7 @@ rb_thread_blocking_region( #include <sys/types.h> #include <netdb.h> #include <unistd.h> +#include <fcntl.h> #include <string.h> #include <asm/types.h> #include <netinet/in.h> @@ -74,6 +75,21 @@ struct nogvl_args { int fd; }; +#ifdef SOCK_CLOEXEC +# define my_SOCK_RAW (SOCK_RAW|SOCK_CLOEXEC) +# define FORCE_CLOEXEC(v) (v) +#else +# define my_SOCK_RAW SOCK_RAW +static VALUE FORCE_CLOEXEC(VALUE io) +{ + int fd = my_fileno(io); + int flags = fcntl(fd, F_SETFD, FD_CLOEXEC); + if (flags == -1) + rb_sys_fail("fcntl(F_SETFD, FD_CLOEXEC)"); + return io; +} +#endif + /* * call-seq: * Raindrops::InetDiagSocket.new -> Socket @@ -83,11 +99,12 @@ struct nogvl_args { static VALUE ids_s_new(VALUE klass) { VALUE argv[3]; + argv[0] = INT2NUM(AF_NETLINK); - argv[1] = INT2NUM(SOCK_RAW); + argv[1] = INT2NUM(my_SOCK_RAW); argv[2] = INT2NUM(NETLINK_INET_DIAG); - return rb_call_super(3, argv); + return FORCE_CLOEXEC(rb_call_super(3, argv)); } /* creates a Ruby ListenStats Struct based on our internal listen_stats */ diff --git a/test/test_inet_diag_socket.rb b/test/test_inet_diag_socket.rb index c40d50e..047dff3 100644 --- a/test/test_inet_diag_socket.rb +++ b/test/test_inet_diag_socket.rb @@ -1,6 +1,7 @@ # -*- encoding: binary -*- require 'test/unit' require 'raindrops' +require 'fcntl' $stderr.sync = $stdout.sync = true class TestInetDiagSocket < Test::Unit::TestCase @@ -8,6 +9,8 @@ class TestInetDiagSocket < Test::Unit::TestCase sock = Raindrops::InetDiagSocket.new assert_kind_of Socket, sock assert_kind_of Fixnum, sock.fileno + flags = sock.fcntl(Fcntl::F_GETFD) + assert_equal Fcntl::FD_CLOEXEC, flags & Fcntl::FD_CLOEXEC assert_nil sock.close end end if RUBY_PLATFORM =~ /linux/ |