Project

General

Profile

Feature #6583 » socket.improve_bind_error.patch

drbrain (Eric Hodel), 06/13/2012 11:42 AM

View differences:

ext/socket/udpsocket.c (working copy)
static VALUE
udp_bind(VALUE sock, VALUE host, VALUE port)
{
VALUE mesg;
rb_io_t *fptr;
struct addrinfo *res0, *res;
......
return INT2FIX(0);
}
freeaddrinfo(res0);
rb_sys_fail("bind(2)");
port = rb_String(port);
mesg = rb_sprintf("bind(2) for \"%s\" port %s",
StringValueCStr(host),
StringValueCStr(port));
rb_sys_fail_str(mesg);
return INT2FIX(0);
}
ext/socket/ipsocket.c (working copy)
{
int type = arg->type;
struct addrinfo *res;
int fd, status = 0;
int fd, status = 0, local = 0;
const char *syscall = 0;
arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM,
......
else {
if (arg->local.res) {
status = bind(fd, arg->local.res->ai_addr, arg->local.res->ai_addrlen);
local = status;
syscall = "bind(2)";
}
......
break;
}
if (status < 0) {
rb_sys_fail(syscall);
VALUE host, port, mesg;
const char * local_mesg;
if (local < 0) {
host = arg->local.host;
port = rb_String(arg->local.serv);
local_mesg = " (local address)";
} else {
host = arg->remote.host;
port = rb_String(arg->remote.serv);
local_mesg = "";
}
mesg = rb_sprintf("%s for \"%s\" port %s%s",
syscall, StringValuePtr(host), StringValuePtr(port),
local_mesg);
rb_sys_fail_str(mesg);
}
arg->fd = -1;
ext/socket/socket.c (working copy)
#include "rubysocket.h"
static VALUE sock_s_unpack_sockaddr_in(VALUE, VALUE);
static void
setup_domain_and_type(VALUE domain, int *dv, VALUE type, int *tv)
{
......
SockAddrStringValue(addr);
GetOpenFile(sock, fptr);
if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr)) < 0)
rb_sys_fail("bind(2)");
if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr)) < 0) {
VALUE host_port = sock_s_unpack_sockaddr_in(sock, addr);
VALUE mesg = rb_sprintf("bind(2) for \"%s\" port %d",
StringValueCStr(RARRAY_PTR(host_port)[1]),
NUM2INT(RARRAY_PTR(host_port)[0]));
rb_sys_fail_str(mesg);
}
return INT2FIX(0);
}
test/socket/test_tcp.rb (working copy)
class TestSocket_TCPSocket < Test::Unit::TestCase
def test_initialize_failure
s = TCPServer.new("localhost", nil)
server_port = s.addr[1]
c = TCPSocket.new("localhost", server_port)
client_port = c.addr[1]
begin
# TCPServer.new uses SO_REUSEADDR so we must create a failure on the
# local address.
TCPSocket.new("localhost", server_port, "localhost", client_port)
flunk "expected SystemCallError"
rescue SystemCallError => e
assert_match "for \"localhost\" port #{client_port}", e.message
end
end
def test_recvfrom
svr = TCPServer.new("localhost", 0)
th = Thread.new {
test/socket/test_socket.rb (working copy)
}
end
def test_bind
Socket.open(Socket::AF_INET, Socket::SOCK_STREAM, 0) {|bound|
bound.bind(Socket.sockaddr_in(0, "127.0.0.1"))
addr = bound.getsockname
port, = Socket.unpack_sockaddr_in(addr)
Socket.open(Socket::AF_INET, Socket::SOCK_STREAM, 0) {|s|
e = assert_raises(Errno::EADDRINUSE) do
s.bind(Socket.sockaddr_in(port, "127.0.0.1"))
end
assert_match "bind(2) for \"127.0.0.1\" port #{port}", e.message
}
}
end
def test_getaddrinfo
# This should not send a DNS query because AF_UNIX.
assert_raise(SocketError) { Socket.getaddrinfo("www.kame.net", 80, "AF_UNIX") }
test/socket/test_udp.rb (working copy)
s.bind(host, 2000)
}
end
def test_bind_addrinuse
host = "127.0.0.1"
port = 2001
in_use = UDPSocket.new
in_use.bind(host, port)
s = UDPSocket.new
e = assert_raises(Errno::EADDRINUSE) do
s.bind(host, port)
end
assert_match "bind(2) for \"#{host}\" port #{port}", e.message
end
end if defined?(UDPSocket)
(1-1/2)