From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS8100 96.47.226.0/23 X-Spam-Status: No, score=-1.5 required=3.0 tests=BAYES_00,RCVD_IN_XBL shortcircuit=no autolearn=no version=3.3.2 X-Original-To: spew@80x24.org Received: from 80x24.org (wannabe.torservers.net [96.47.226.22]) by dcvr.yhbt.net (Postfix) with ESMTP id CB9C91FACE for ; Tue, 12 May 2015 00:06:36 +0000 (UTC) From: Eric Wong To: spew@80x24.org Subject: [PATCH 2/2] socket: accept_nonblock supports "nonblock: false" kwarg Date: Tue, 12 May 2015 00:06:31 +0000 Message-Id: <1431389191-915-2-git-send-email-e@80x24.org> In-Reply-To: <1431389191-915-1-git-send-email-e@80x24.org> References: <1431389191-915-1-git-send-email-e@80x24.org> List-Id: An application wanting to do non-blocking accept may want to create a blocking socket, allow If this patch is accepted, I'd also like to support the opposite for blocking accept calls: a = s.accept(nonblock: true) # blocking accept syscall a.nonblock? # => true s.nonblock? # => false --- ext/socket/init.c | 14 ++++++++++---- test/socket/test_nonblock.rb | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/ext/socket/init.c b/ext/socket/init.c index 317dd67..0bafec4 100644 --- a/ext/socket/init.c +++ b/ext/socket/init.c @@ -29,7 +29,7 @@ VALUE rb_cSOCKSSocket; #endif int rsock_do_not_reverse_lookup = 1; -static VALUE sym_exception, sym_wait_readable; +static VALUE sym_exception, sym_wait_readable, sym_nonblock; void rsock_raise_socket_error(const char *reason, int error) @@ -526,16 +526,21 @@ rsock_s_accept_nonblock(int argc, VALUE *argv, VALUE klass, rb_io_t *fptr, { int fd2; int ex = 1; + int nonblock = 1; VALUE opts = Qnil; rb_scan_args(argc, argv, "0:", &opts); - if (!NIL_P(opts) && Qfalse == rb_hash_lookup2(opts, sym_exception, Qundef)) - ex = 0; + if (!NIL_P(opts)) { + if (Qfalse == rb_hash_lookup2(opts, sym_exception, Qundef)) + ex = 0; + if (Qfalse == rb_hash_lookup2(opts, sym_nonblock, Qundef)) + nonblock = 0; + } rb_secure(3); rb_io_set_nonblock(fptr); - fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len, 1); + fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len, nonblock); if (fd2 < 0) { switch (errno) { case EAGAIN: @@ -639,4 +644,5 @@ rsock_init_socket_init(void) #undef rb_intern sym_exception = ID2SYM(rb_intern("exception")); sym_wait_readable = ID2SYM(rb_intern("wait_readable")); + sym_nonblock = ID2SYM(rb_intern("nonblock")); } diff --git a/test/socket/test_nonblock.rb b/test/socket/test_nonblock.rb index 5268252..a862784 100644 --- a/test/socket/test_nonblock.rb +++ b/test/socket/test_nonblock.rb @@ -27,6 +27,20 @@ class TestSocketNonblock < Test::Unit::TestCase assert_equal(Socket.unpack_sockaddr_in(c.getsockname), Socket.unpack_sockaddr_in(sockaddr)) if s.respond_to?(:nonblock?) assert s.nonblock?, 'accepted socket is non-blocking' + + tf = [ true, false ] + assert_equal(tf, tf.map do |nb| + begin + b = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0) + b.connect(serv.getsockname) + IO.select([serv]) + a, _= serv.accept_nonblock(nonblock: nb) + a.nonblock? + ensure + a.close if a + b.close if b + end + end) end ensure serv.close if serv -- EW