From c22f2b5ebccbca8e04aa22821964f67c4a81c675 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 6 Jul 2011 19:11:47 -0700 Subject: export SOCK_NONBLOCK, SOCK_CLOEXEC constants in Kgio It's more reliable than relying on IO::NONBLOCK and Fcntl::FD_CLOEXEC constants. The existing constants are not guaranteed to be equivalent to what accept4() takes even though the current Linux implementation does it this way. --- ext/kgio/accept.c | 20 +++++++++++++++---- test/test_accept_flags.rb | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 test/test_accept_flags.rb diff --git a/ext/kgio/accept.c b/ext/kgio/accept.c index 1a125ca..f14c791 100644 --- a/ext/kgio/accept.c +++ b/ext/kgio/accept.c @@ -283,8 +283,8 @@ static VALUE addr_bang(VALUE io) * value of +Kgio.accept_cloexec+ and +Kgio.accept_nonblock+. +flags+ * is a bitmask that may contain any combination of: * - * - Fcntl::FD_CLOEXEC - close-on-exec flag - * - IO::NONBLOCK - non-blocking flag + * - Kgio::SOCK_CLOEXEC - close-on-exec flag + * - Kgio::SOCK_NONBLOCK - non-blocking flag */ static VALUE tcp_tryaccept(int argc, VALUE *argv, VALUE self) { @@ -320,8 +320,8 @@ static VALUE tcp_tryaccept(int argc, VALUE *argv, VALUE self) * value of +Kgio.accept_cloexec+ and +Kgio.accept_nonblock+. +flags+ * is a bitmask that may contain any combination of: * - * - Fcntl::FD_CLOEXEC - close-on-exec flag - * - IO::NONBLOCK - non-blocking flag + * - Kgio::SOCK_CLOEXEC - close-on-exec flag + * - Kgio::SOCK_NONBLOCK - non-blocking flag */ static VALUE tcp_accept(int argc, VALUE *argv, VALUE self) { @@ -496,6 +496,18 @@ void init_kgio_accept(void) VALUE cUNIXServer, cTCPServer; VALUE mKgio = rb_define_module("Kgio"); + /* + * this maps to the SOCK_NONBLOCK constant in Linux for setting + * the non-blocking flag on newly accepted sockets. + */ + rb_define_const(mKgio, "SOCK_NONBLOCK", INT2NUM(SOCK_NONBLOCK)); + + /* + * this maps to the SOCK_CLOEXEC constant in Linux for setting + * the close-on-exec flag on newly accepted descriptors. + */ + rb_define_const(mKgio, "SOCK_CLOEXEC", INT2NUM(SOCK_CLOEXEC)); + localhost = rb_const_get(mKgio, rb_intern("LOCALHOST")); cKgio_Socket = rb_const_get(mKgio, rb_intern("Socket")); cClientSocket = cKgio_Socket; diff --git a/test/test_accept_flags.rb b/test/test_accept_flags.rb new file mode 100644 index 0000000..3aae216 --- /dev/null +++ b/test/test_accept_flags.rb @@ -0,0 +1,49 @@ +require 'test/unit' +require 'fcntl' +require 'io/nonblock' +$-w = true +require 'kgio' + +class TestAcceptFlags < Test::Unit::TestCase + def test_accept_flags + @host = ENV["TEST_HOST"] || '127.0.0.1' + @srv = Kgio::TCPServer.new(@host, 0) + @port = @srv.addr[1] + + client = TCPSocket.new(@host, @port) + accepted = @srv.kgio_accept(nil, Kgio::SOCK_NONBLOCK) + assert_instance_of Kgio::Socket, accepted + assert accepted.nonblock? + flags = accepted.fcntl(Fcntl::F_GETFD) + assert_equal 0, flags & Fcntl::FD_CLOEXEC + assert_nil client.close + assert_nil accepted.close + + client = TCPSocket.new(@host, @port) + accepted = @srv.kgio_accept(nil, Kgio::SOCK_CLOEXEC) + assert_instance_of Kgio::Socket, accepted + assert ! accepted.nonblock? + flags = accepted.fcntl(Fcntl::F_GETFD) + assert_equal Fcntl::FD_CLOEXEC, flags & Fcntl::FD_CLOEXEC + assert_nil client.close + assert_nil accepted.close + + client = TCPSocket.new(@host, @port) + accepted = @srv.kgio_accept(nil, Kgio::SOCK_CLOEXEC|Kgio::SOCK_NONBLOCK) + assert_instance_of Kgio::Socket, accepted + assert accepted.nonblock? + flags = accepted.fcntl(Fcntl::F_GETFD) + assert_equal Fcntl::FD_CLOEXEC, flags & Fcntl::FD_CLOEXEC + assert_nil client.close + assert_nil accepted.close + + client = TCPSocket.new(@host, @port) + accepted = @srv.kgio_accept(nil, Kgio::SOCK_CLOEXEC|Kgio::SOCK_NONBLOCK) + assert_instance_of Kgio::Socket, accepted + assert accepted.nonblock? + flags = accepted.fcntl(Fcntl::F_GETFD) + assert_equal Fcntl::FD_CLOEXEC, flags & Fcntl::FD_CLOEXEC + assert_nil client.close + assert_nil accepted.close + end +end -- cgit v1.2.3-24-ge0c7