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
#endif
int rsock_do_not_reverse_lookup = 1;
static VALUE sym_exception, sym_wait_readable;
void
rsock_raise_socket_error(const char *reason, int error)
......
return ret;
}
VALUE
rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
rsock_s_accept_nonblock(int argc, VALUE *argv, VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
{
int fd2;
int ex = 1;
VALUE opts = Qnil;
rb_scan_args(argc, argv, "0:", &opts);
if (!NIL_P(opts) && Qfalse == rb_hash_aref(opts, sym_exception))
ex = 0;
rb_secure(3);
rb_io_set_nonblock(fptr);
......
#if defined EPROTO
case EPROTO:
#endif
if (!ex)
return sym_wait_readable;
rb_readwrite_sys_fail(RB_IO_WAIT_READABLE, "accept(2) would block");
}
rb_sys_fail("accept(2)");
......
rsock_init_addrinfo();
rsock_init_sockifaddr();
rsock_init_socket_constants();
sym_exception = ID2SYM(rb_intern("exception"));
sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
}
ext/socket/rubysocket.h
int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks);
VALUE rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len);
VALUE rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len);
VALUE rsock_s_accept_nonblock(int argc, VALUE *argv, VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len);
VALUE rsock_sock_listen(VALUE sock, VALUE log);
VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data);
ext/socket/socket.c
* * Socket#accept
*/
static VALUE
sock_accept_nonblock(VALUE sock)
sock_accept_nonblock(int argc, VALUE *argv, VALUE sock)
{
rb_io_t *fptr;
VALUE sock2;
......
socklen_t len = (socklen_t)sizeof buf;
GetOpenFile(sock, fptr);
sock2 = rsock_s_accept_nonblock(rb_cSocket, fptr, &buf.addr, &len);
sock2 = rsock_s_accept_nonblock(argc, argv, rb_cSocket, fptr, &buf.addr, &len);
if (SYMBOL_P(sock2)) /* :wait_readable */
return sock2;
return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len));
}
......
rb_define_method(rb_cSocket, "bind", sock_bind, 1);
rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1);
rb_define_method(rb_cSocket, "accept", sock_accept, 0);
rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, -1);
rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
ext/socket/tcpserver.c
* * Socket#accept
*/
static VALUE
tcp_accept_nonblock(VALUE sock)
tcp_accept_nonblock(int argc, VALUE *argv, VALUE sock)
{
rb_io_t *fptr;
union_sockaddr from;
......
GetOpenFile(sock, fptr);
fromlen = (socklen_t)sizeof(from);
return rsock_s_accept_nonblock(rb_cTCPSocket, fptr, &from.addr, &fromlen);
return rsock_s_accept_nonblock(argc, argv, rb_cTCPSocket, fptr, &from.addr, &fromlen);
}
/*
......
*/
rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, 0);
rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, -1);
rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
rb_define_method(rb_cTCPServer, "listen", rsock_sock_listen, 1); /* in socket.c */
ext/socket/unixserver.c
* * Socket#accept
*/
static VALUE
unix_accept_nonblock(VALUE sock)
unix_accept_nonblock(int argc, VALUE *argv, VALUE sock)
{
rb_io_t *fptr;
struct sockaddr_un from;
......
GetOpenFile(sock, fptr);
fromlen = (socklen_t)sizeof(from);
return rsock_s_accept_nonblock(rb_cUNIXSocket, fptr,
return rsock_s_accept_nonblock(argc, argv, rb_cUNIXSocket, fptr,
(struct sockaddr *)&from, &fromlen);
}
......
rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket);
rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1);
rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
rb_define_method(rb_cUNIXServer, "accept_nonblock", unix_accept_nonblock, 0);
rb_define_method(rb_cUNIXServer, "accept_nonblock", unix_accept_nonblock, -1);
rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0);
rb_define_method(rb_cUNIXServer, "listen", rsock_sock_listen, 1); /* in socket.c */
#endif
test/socket/test_nonblock.rb
serv.bind(Socket.sockaddr_in(0, "127.0.0.1"))
serv.listen(5)
assert_raise(IO::WaitReadable) { serv.accept_nonblock }
assert_equal :wait_readable, serv.accept_nonblock(exception: false)
assert_raise(IO::WaitReadable) { serv.accept_nonblock(exception: true) }
c = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
c.connect(serv.getsockname)
begin
test/socket/test_tcp.rb
th.join if th
sock.close if sock
end
def test_accept_nonblock
svr = TCPServer.new("localhost", 0)
assert_raises(IO::WaitReadable) { svr.accept_nonblock }
assert_equal :wait_readable, svr.accept_nonblock(exception: false)
assert_raises(IO::WaitReadable) { svr.accept_nonblock(exception: true) }
end
end if defined?(TCPSocket)
test/socket/test_unix.rb
assert(s0.closed?)
end
def test_accept_nonblock
bound_unix_socket(UNIXServer) {|serv, path|
assert_raises(IO::WaitReadable) { serv.accept_nonblock }
assert_raises(IO::WaitReadable) { serv.accept_nonblock(exception: true) }
assert_equal :wait_readable, serv.accept_nonblock(exception: false)
}
end
end if defined?(UNIXSocket) && /cygwin/ !~ RUBY_PLATFORM
    (1-1/1)