From: Francis Cianfrocca Date: 2006-05-27T11:28:57+09:00 Subject: Re: Nonblocking accept ------=_Part_299407_26536074.1148696934652 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Thanks for the patch, I'll test as soon as I can. In regard to datagrams, what I meant was nonblocking recvfrom. I haven't tried that one yet. Let me repeat- the performance boost from nonblocking connect is really great. Thanks again. On 5/26/06, Tanaka Akira wrote: > > In article <3a94cf510605260529x658e20e1q7d9754266675c3d5@mail.gmail.com>, > "Francis Cianfrocca" writes: > > > Thanks to the Matz and colleagues for adding the *_nonblock functions. > They > > have been a huge help. I've already gotten some big performance > improvements > > in the EventMachine event-processing library. I thought it was a little > > strange that accept_nonblock is not available for TCPServer (because it > > inherits from IO rather than Socket) but it wasn't hard to work around > that. > > (Just create a Socket object and call bind and listen on it myself.) Th= e > > nonblock functions seem to work well with files and unix-domain sockets= . > I > > haven't tested datagrams yet but will do so shortly. > > Since accept is for connection oriented sockets, UDP doesn't need it. > > Index: ext/socket/socket.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > RCS file: /src/ruby/ext/socket/socket.c,v > retrieving revision 1.164 > diff -u -p -r1.164 socket.c > --- ext/socket/socket.c 25 May 2006 23:43:29 -0000 1.164 > +++ ext/socket/socket.c 27 May 2006 01:52:19 -0000 > @@ -1383,6 +1383,20 @@ tcp_svr_init(argc, argv, sock) > } > > static VALUE > +s_accept_nonblock(VALUE klass, OpenFile *fptr, struct sockaddr *sockaddr= , > socklen_t *len) > +{ > + int fd2; > + > + rb_secure(3); > + rb_io_set_nonblock(fptr); > + fd2 =3D accept(fptr->fd, (struct sockaddr*)sockaddr, len); > + if (fd2 < 0) { > + rb_sys_fail("accept(2)"); > + } > + return init_sock(rb_obj_alloc(klass), fd2); > +} > + > +static VALUE > s_accept(klass, fd, sockaddr, len) > VALUE klass; > int fd; > @@ -1435,6 +1449,49 @@ tcp_accept(sock) > (struct sockaddr*)&from, &fromlen); > } > > +/* > + * call-seq: > + * tcpserver.accept_nonblock =3D> tcpsocket > + * > + * Accepts an incoming connection using accept(2) after > + * O_NONBLOCK is set for the underlying file descriptor. > + * It returns an accepted TCPSocket for the incoming connection. > + * > + * =3D=3D=3D Example > + * require 'socket' > + * serv =3D TCPServer.new(2202) > + * begin > + * sock =3D serv.accept_nonblock > + * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, > Errno::EINTR > + * IO.select([serv]) > + * retry > + * end > + * # sock is an accepted socket. > + * > + * Refer to Socket#accept for the exceptions that may be thrown if the > call > + * to TCPServer#accept_nonblock fails. > + * > + * TCPServer#accept_nonblock may raise any error corresponding to > accept(2) failure, > + * including Errno::EAGAIN. > + * > + * =3D=3D=3D See > + * * TCPServer#accept > + * * Socket#accept > + */ > +static VALUE > +tcp_accept_nonblock(sock) > + VALUE sock; > +{ > + OpenFile *fptr; > + struct sockaddr_storage from; > + socklen_t fromlen; > + > + GetOpenFile(sock, fptr); > + fromlen =3D sizeof(from); > + return s_accept_nonblock(rb_cTCPSocket, fptr, > + (struct sockaddr *)&from, &fromlen); > +} > + > static VALUE > tcp_sysaccept(sock) > VALUE sock; > @@ -1925,6 +1982,49 @@ unix_accept(sock) > (struct sockaddr*)&from, &fromlen); > } > > +/* > + * call-seq: > + * unixserver.accept_nonblock =3D> unixsocket > + * > + * Accepts an incoming connection using accept(2) after > + * O_NONBLOCK is set for the underlying file descriptor. > + * It returns an accepted UNIXSocket for the incoming connection. > + * > + * =3D=3D=3D Example > + * require 'socket' > + * serv =3D UNIXServer.new("/tmp/sock") > + * begin > + * sock =3D serv.accept_nonblock > + * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, > Errno::EINTR > + * IO.select([serv]) > + * retry > + * end > + * # sock is an accepted socket. > + * > + * Refer to Socket#accept for the exceptions that may be thrown if the > call > + * to UNIXServer#accept_nonblock fails. > + * > + * UNIXServer#accept_nonblock may raise any error corresponding to > accept(2) failure, > + * including Errno::EAGAIN. > + * > + * =3D=3D=3D See > + * * UNIXServer#accept > + * * Socket#accept > + */ > +static VALUE > +unix_accept_nonblock(sock) > + VALUE sock; > +{ > + OpenFile *fptr; > + struct sockaddr_storage from; > + socklen_t fromlen; > + > + GetOpenFile(sock, fptr); > + fromlen =3D sizeof(from); > + return s_accept_nonblock(rb_cUNIXSocket, fptr, > + (struct sockaddr *)&from, &fromlen); > +} > + > static VALUE > unix_sysaccept(sock) > VALUE sock; > @@ -2784,19 +2884,12 @@ sock_accept_nonblock(sock) > VALUE sock; > { > OpenFile *fptr; > - int fd2; > VALUE sock2; > char buf[1024]; > socklen_t len =3D sizeof buf; > > GetOpenFile(sock, fptr); > - rb_io_set_nonblock(fptr); > - fd2 =3D accept(fptr->fd, (struct sockaddr*)buf, &len); > - if (fd2 < 0) { > - rb_sys_fail("accept(2)"); > - } > - sock2 =3D init_sock(rb_obj_alloc(rb_cSocket), fd2); > - > + sock2 =3D s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)buf= , > &len); > return rb_assoc_new(sock2, rb_str_new(buf, len)); > } > > @@ -3414,6 +3507,7 @@ Init_socket() > rb_cTCPServer =3D rb_define_class("TCPServer", rb_cTCPSocket); > rb_define_global_const("TCPserver", rb_cTCPServer); > 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, "sysaccept", tcp_sysaccept, 0); > rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1); > rb_define_method(rb_cTCPServer, "listen", sock_listen, 1); > @@ -3442,6 +3536,7 @@ Init_socket() > rb_define_global_const("UNIXserver", rb_cUNIXServer); > 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, "sysaccept", unix_sysaccept, 0); > rb_define_method(rb_cUNIXServer, "listen", sock_listen, 1); > #endif > > -- > Tanaka Akira > > ------=_Part_299407_26536074.1148696934652--