Feature #6583 » socket.improve_bind_error.patch
| 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)
|
||