From: nobu.nokada@... Date: 2002-04-04T01:02:29+09:00 Subject: Re: TCPSocket::new in ruby 1.7 Hi, At Wed, 3 Apr 2002 16:51:19 +0900, Nikolay Elkov wrote: > irb(main):006:0> begin > irb(main):007:1* timeout (5) do > irb(main):008:2* s = TCPSocket::new('somehost' , 233, 'myhost', 45678) > irb(main):009:2> end > irb(main):010:1> rescue TimeoutError > irb(main):011:1> puts "timeout" > irb(main):012:1> end > timeout > nil > irb(main):013:0> > > produces > > TCP httpsvr1:45678 myhost:0 LISTENING > > There is no, at lead I can't think of any, a way to close the LISTENING > socket. > Is it supposed to work like this and if so, how do I close the socket? Following patch may fix it? Index: ext/socket/socket.c =================================================================== RCS file: /cvs/ruby/src/ruby/ext/socket/socket.c,v retrieving revision 1.73 diff -u -2 -p -r1.73 socket.c --- ext/socket/socket.c 2002/04/02 06:12:04 1.73 +++ ext/socket/socket.c 2002/04/03 16:01:50 @@ -846,26 +846,51 @@ load_addr_info(h, serv, type, res) } -static VALUE -init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type) - VALUE sock, remote_host, remote_serv, local_host, local_serv; +struct inetsock_arg +{ + VALUE sock; + struct { + VALUE host, serv; + struct addrinfo *res; + } remote, local; int type; +}; + +static VALUE +inetsock_freeaddrinfo(arg) + struct inetsock_arg *arg; +{ + if (arg->remote.res) { + freeaddrinfo(arg->remote.res); + arg->remote.res = 0; + } + if (arg->local.res) { + freeaddrinfo(arg->local.res); + arg->local.res = 0; + } + return Qnil; +} + +static VALUE +init_inetsock_internal(arg) + struct inetsock_arg *arg; { - struct addrinfo hints, *res, *res_remote, *res_local = NULL; + int type = arg->type; + struct addrinfo hints, *res; int fd, status; char *syscall; - res_remote = sock_addrinfo(remote_host, remote_serv, SOCK_STREAM, - (type == INET_SERVER) ? AI_PASSIVE : 0); + arg->remote.res = sock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM, + (type == INET_SERVER) ? AI_PASSIVE : 0); /* * Maybe also accept a local address */ - if (type != INET_SERVER && (!NIL_P(local_host) || !NIL_P(local_serv))) { - res_local = sock_addrinfo(local_host, local_serv, SOCK_STREAM, - (type == INET_SERVER) ? AI_PASSIVE : 0); + if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) { + arg->local.res = sock_addrinfo(arg->local.host, arg->local.serv, SOCK_STREAM, + (type == INET_SERVER) ? AI_PASSIVE : 0); } fd = -1; - for (res = res_remote; res; res = res->ai_next) { + for (res = arg->remote.res; res; res = res->ai_next) { status = ruby_socket(res->ai_family,res->ai_socktype,res->ai_protocol); syscall = "socket(2)"; @@ -884,6 +909,6 @@ init_inetsock(sock, remote_host, remote_ } else { - if (res_local) { - status = bind(fd, res_local->ai_addr, res_local->ai_addrlen); + if (arg->local.res) { + status = bind(fd, arg->local.res->ai_addr, arg->local.res->ai_addrlen); syscall = "bind(2)"; } @@ -914,8 +939,4 @@ init_inetsock(sock, remote_host, remote_ close(fd); #endif - freeaddrinfo(res_remote); - if (res_local) { - freeaddrinfo(res_local); - } rb_sys_fail(syscall); } @@ -925,8 +946,23 @@ init_inetsock(sock, remote_host, remote_ /* create new instance */ - if (res_local) - freeaddrinfo(res_local); - freeaddrinfo(res_remote); - return init_sock(sock, fd); + return init_sock(arg->sock, fd); +} + +static VALUE +init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type) + VALUE sock, remote_host, remote_serv, local_host, local_serv; + int type; +{ + struct inetsock_arg arg; + arg.sock = sock; + arg.remote.host = remote_host; + arg.remote.serv = remote_serv; + arg.remote.res = 0; + arg.local.host = local_host; + arg.local.serv = local_serv; + arg.local.res = 0; + arg.type = type; + return rb_ensure(init_inetsock_internal, (VALUE)&arg, + inetsock_freeaddrinfo, (VALUE)&arg); } -- Nobu Nakada