Project

General

Profile

Feature #9091 ยป 0001-accept_nonblock-supports-exception-false.patch

normalperson (Eric Wong), 11/07/2013 12:33 PM

View differences:

ext/socket/init.c
29 29
#endif
30 30

  
31 31
int rsock_do_not_reverse_lookup = 1;
32
static VALUE sym_exception, sym_wait_readable;
32 33

  
33 34
void
34 35
rsock_raise_socket_error(const char *reason, int error)
......
522 523
    return ret;
523 524
}
524 525

  
525

  
526 526
VALUE
527
rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
527
rsock_s_accept_nonblock(int argc, VALUE *argv, VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
528 528
{
529 529
    int fd2;
530
    int ex = 1;
531
    VALUE opts = Qnil;
532

  
533
    rb_scan_args(argc, argv, "0:", &opts);
534

  
535
    if (!NIL_P(opts) && Qfalse == rb_hash_aref(opts, sym_exception))
536
	ex = 0;
530 537

  
531 538
    rb_secure(3);
532 539
    rb_io_set_nonblock(fptr);
......
541 548
#if defined EPROTO
542 549
	  case EPROTO:
543 550
#endif
551
            if (!ex)
552
		return sym_wait_readable;
544 553
            rb_readwrite_sys_fail(RB_IO_WAIT_READABLE, "accept(2) would block");
545 554
	}
546 555
        rb_sys_fail("accept(2)");
......
629 638
    rsock_init_addrinfo();
630 639
    rsock_init_sockifaddr();
631 640
    rsock_init_socket_constants();
641

  
642
    sym_exception = ID2SYM(rb_intern("exception"));
643
    sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
632 644
}
ext/socket/rubysocket.h
333 333
int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks);
334 334

  
335 335
VALUE rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len);
336
VALUE rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len);
336
VALUE rsock_s_accept_nonblock(int argc, VALUE *argv, VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len);
337 337
VALUE rsock_sock_listen(VALUE sock, VALUE log);
338 338

  
339 339
VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data);
ext/socket/socket.c
896 896
 * * Socket#accept
897 897
 */
898 898
static VALUE
899
sock_accept_nonblock(VALUE sock)
899
sock_accept_nonblock(int argc, VALUE *argv, VALUE sock)
900 900
{
901 901
    rb_io_t *fptr;
902 902
    VALUE sock2;
......
904 904
    socklen_t len = (socklen_t)sizeof buf;
905 905

  
906 906
    GetOpenFile(sock, fptr);
907
    sock2 = rsock_s_accept_nonblock(rb_cSocket, fptr, &buf.addr, &len);
907
    sock2 = rsock_s_accept_nonblock(argc, argv, rb_cSocket, fptr, &buf.addr, &len);
908

  
909
    if (SYMBOL_P(sock2)) /* :wait_readable */
910
	return sock2;
908 911
    return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len));
909 912
}
910 913

  
......
2095 2098
    rb_define_method(rb_cSocket, "bind", sock_bind, 1);
2096 2099
    rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1);
2097 2100
    rb_define_method(rb_cSocket, "accept", sock_accept, 0);
2098
    rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
2101
    rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, -1);
2099 2102
    rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
2100 2103

  
2101 2104
    rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
ext/socket/tcpserver.c
98 98
 * * Socket#accept
99 99
 */
100 100
static VALUE
101
tcp_accept_nonblock(VALUE sock)
101
tcp_accept_nonblock(int argc, VALUE *argv, VALUE sock)
102 102
{
103 103
    rb_io_t *fptr;
104 104
    union_sockaddr from;
......
106 106

  
107 107
    GetOpenFile(sock, fptr);
108 108
    fromlen = (socklen_t)sizeof(from);
109
    return rsock_s_accept_nonblock(rb_cTCPSocket, fptr, &from.addr, &fromlen);
109
    return rsock_s_accept_nonblock(argc, argv, rb_cTCPSocket, fptr, &from.addr, &fromlen);
110 110
}
111 111

  
112 112
/*
......
171 171
     */
172 172
    rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
173 173
    rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
174
    rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, 0);
174
    rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, -1);
175 175
    rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
176 176
    rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
177 177
    rb_define_method(rb_cTCPServer, "listen", rsock_sock_listen, 1); /* in socket.c */
ext/socket/unixserver.c
91 91
 * * Socket#accept
92 92
 */
93 93
static VALUE
94
unix_accept_nonblock(VALUE sock)
94
unix_accept_nonblock(int argc, VALUE *argv, VALUE sock)
95 95
{
96 96
    rb_io_t *fptr;
97 97
    struct sockaddr_un from;
......
99 99

  
100 100
    GetOpenFile(sock, fptr);
101 101
    fromlen = (socklen_t)sizeof(from);
102
    return rsock_s_accept_nonblock(rb_cUNIXSocket, fptr,
102
    return rsock_s_accept_nonblock(argc, argv, rb_cUNIXSocket, fptr,
103 103
			           (struct sockaddr *)&from, &fromlen);
104 104
}
105 105

  
......
148 148
    rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket);
149 149
    rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1);
150 150
    rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
151
    rb_define_method(rb_cUNIXServer, "accept_nonblock", unix_accept_nonblock, 0);
151
    rb_define_method(rb_cUNIXServer, "accept_nonblock", unix_accept_nonblock, -1);
152 152
    rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0);
153 153
    rb_define_method(rb_cUNIXServer, "listen", rsock_sock_listen, 1); /* in socket.c */
154 154
#endif
test/socket/test_nonblock.rb
13 13
    serv.bind(Socket.sockaddr_in(0, "127.0.0.1"))
14 14
    serv.listen(5)
15 15
    assert_raise(IO::WaitReadable) { serv.accept_nonblock }
16
    assert_equal :wait_readable, serv.accept_nonblock(exception: false)
17
    assert_raise(IO::WaitReadable) { serv.accept_nonblock(exception: true) }
16 18
    c = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
17 19
    c.connect(serv.getsockname)
18 20
    begin
test/socket/test_tcp.rb
77 77
    th.join if th
78 78
    sock.close if sock
79 79
  end
80

  
81
  def test_accept_nonblock
82
    svr = TCPServer.new("localhost", 0)
83
    assert_raises(IO::WaitReadable) { svr.accept_nonblock }
84
    assert_equal :wait_readable, svr.accept_nonblock(exception: false)
85
    assert_raises(IO::WaitReadable) { svr.accept_nonblock(exception: true) }
86
  end
80 87
end if defined?(TCPSocket)
test/socket/test_unix.rb
604 604
    assert(s0.closed?)
605 605
  end
606 606

  
607
  def test_accept_nonblock
608
    bound_unix_socket(UNIXServer) {|serv, path|
609
      assert_raises(IO::WaitReadable) { serv.accept_nonblock }
610
      assert_raises(IO::WaitReadable) { serv.accept_nonblock(exception: true) }
611
      assert_equal :wait_readable, serv.accept_nonblock(exception: false)
612
    }
613
  end
607 614
end if defined?(UNIXSocket) && /cygwin/ !~ RUBY_PLATFORM
608
-