Project

General

Profile

Feature #6583 ยป socket.improve_bind_error.2.patch

drbrain (Eric Hodel), 07/04/2012 11:07 AM

View differences:

ext/socket/rubysocket.h (working copy)
306 306
void rsock_init_sockopt(void);
307 307
void rsock_init_socket_init(void);
308 308

  
309
void rsock_sys_fail_host_port(const char *, VALUE, VALUE);
310
void rsock_sys_fail_path(const char *, VALUE);
311
void rsock_sys_fail_sockaddr(const char *, VALUE, VALUE);
312

  
309 313
#endif
ext/socket/udpsocket.c (working copy)
93 93
    arg.fd = fptr->fd;
94 94
    ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
95 95
		    rsock_freeaddrinfo, (VALUE)arg.res);
96
    if (!ret) rb_sys_fail("connect(2)");
96
    if (!ret) rsock_sys_fail_host_port("connect(2)", host, port);
97 97
    return INT2FIX(0);
98 98
}
99 99

  
......
126 126
	return INT2FIX(0);
127 127
    }
128 128
    freeaddrinfo(res0);
129
    rb_sys_fail("bind(2)");
129

  
130
    rsock_sys_fail_host_port("bind(2)", host, port);
131

  
130 132
    return INT2FIX(0);
131 133
}
132 134

  
......
187 189
	}
188 190
    }
189 191
    freeaddrinfo(res0);
190
    rb_sys_fail("sendto(2)");
192
    rsock_sys_fail_host_port("sendto(2)", host, port);
191 193
    return INT2FIX(n);
192 194
}
193 195

  
ext/socket/init.c (working copy)
47 47
    struct stat sbuf;
48 48

  
49 49
    if (fstat(fd, &sbuf) < 0)
50
        rb_sys_fail(0);
50
        rb_sys_fail("fstat(2)");
51 51
    rb_update_max_fd(fd);
52 52
    if (!S_ISSOCK(sbuf.st_mode))
53 53
        rb_raise(rb_eArgError, "not a socket file descriptor");
......
465 465
#ifdef F_GETFL
466 466
    flags = fcntl(fd, F_GETFL);
467 467
    if (flags == -1) {
468
        rb_sys_fail(0);
468
        rb_sys_fail("fnctl(2)");
469 469
    }
470 470
#else
471 471
    flags = 0;
472 472
#endif
473 473
    flags |= O_NONBLOCK;
474 474
    if (fcntl(fd, F_SETFL, flags) == -1) {
475
        rb_sys_fail(0);
475
        rb_sys_fail("fnctl(2)");
476 476
    }
477 477
}
478 478

  
......
574 574
	    retry = 0;
575 575
	    goto retry;
576 576
	}
577
	rb_sys_fail(0);
577
	rb_sys_fail("accept(2)");
578 578
    }
579 579
    rb_update_max_fd(fd2);
580 580
    if (!klass) return INT2NUM(fd2);
ext/socket/ipsocket.c (working copy)
43 43
{
44 44
    int type = arg->type;
45 45
    struct addrinfo *res;
46
    int fd, status = 0;
46
    int fd, status = 0, local = 0;
47 47
    const char *syscall = 0;
48 48

  
49 49
    arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM,
......
81 81
	else {
82 82
	    if (arg->local.res) {
83 83
		status = bind(fd, arg->local.res->ai_addr, arg->local.res->ai_addrlen);
84
		local = status;
84 85
		syscall = "bind(2)";
85 86
	    }
86 87

  
......
99 100
	    break;
100 101
    }
101 102
    if (status < 0) {
102
	rb_sys_fail(syscall);
103
	VALUE host, port;
104

  
105
	if (local < 0) {
106
	    host = arg->local.host;
107
	    port = arg->local.serv;
108
	} else {
109
	    host = arg->remote.host;
110
	    port = arg->remote.serv;
111
	}
112

  
113
	rsock_sys_fail_host_port(syscall, host, port);
103 114
    }
104 115

  
105 116
    arg->fd = -1;
ext/socket/socket.c (working copy)
10 10

  
11 11
#include "rubysocket.h"
12 12

  
13
static VALUE sock_s_unpack_sockaddr_in(VALUE, VALUE);
14

  
15
void
16
rsock_sys_fail_host_port(const char *mesg, VALUE host, VALUE port)
17
{
18
    VALUE message;
19

  
20
    port = rb_String(port);
21

  
22
    message = rb_sprintf("%s for \"%s\" port %s",
23
	    mesg, StringValueCStr(host), StringValueCStr(port));
24

  
25
    rb_sys_fail_str(message);
26
}
27

  
28
void
29
rsock_sys_fail_path(const char *mesg, VALUE path)
30
{
31
    VALUE message = rb_sprintf("%s for \"%s\"",
32
	    mesg, StringValueCStr(path));
33

  
34
    rb_sys_fail_str(message);
35
}
36

  
37
void
38
rsock_sys_fail_sockaddr(const char *mesg, VALUE sock, VALUE addr)
39
{
40
    VALUE host_port = sock_s_unpack_sockaddr_in(sock, addr);
41

  
42
    rsock_sys_fail_host_port(mesg,
43
	    RARRAY_PTR(host_port)[1],
44
	    RARRAY_PTR(host_port)[0]);
45
}
46

  
13 47
static void
14 48
setup_domain_and_type(VALUE domain, int *dv, VALUE type, int *tv)
15 49
{
......
306 340
    fd = fptr->fd;
307 341
    n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr), 0);
308 342
    if (n < 0) {
309
	rb_sys_fail("connect(2)");
343
	rsock_sys_fail_sockaddr("connect(2)", sock, addr);
310 344
    }
311 345

  
312 346
    return INT2FIX(n);
......
368 402
    if (n < 0) {
369 403
        if (errno == EINPROGRESS)
370 404
            rb_mod_sys_fail(rb_mWaitWritable, "connect(2) would block");
371
	rb_sys_fail("connect(2)");
405
	rsock_sys_fail_sockaddr("connect(2)", sock, addr);
372 406
    }
373 407

  
374 408
    return INT2FIX(n);
......
468 502
    SockAddrStringValue(addr);
469 503
    GetOpenFile(sock, fptr);
470 504
    if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr)) < 0)
471
	rb_sys_fail("bind(2)");
505
	rsock_sys_fail_sockaddr("bind(2)", sock, addr);
472 506

  
473 507
    return INT2FIX(0);
474 508
}
......
903 937

  
904 938
    rb_secure(3);
905 939
    if (gethostname(buf, (int)sizeof buf - 1) < 0)
906
	rb_sys_fail("gethostname");
940
	rb_sys_fail("gethostname(3)");
907 941

  
908 942
    buf[sizeof buf - 1] = '\0';
909 943
    return rb_str_new2(buf);
......
1586 1620

  
1587 1621
    fd = socket(AF_INET, SOCK_DGRAM, 0);
1588 1622
    if (fd == -1)
1589
        rb_sys_fail("socket");
1623
        rb_sys_fail("socket(2)");
1590 1624

  
1591 1625
    memset(&ln, 0, sizeof(ln));
1592 1626
    ln.lifn_family = AF_UNSPEC;
......
1656 1690

  
1657 1691
    fd = socket(AF_INET, SOCK_DGRAM, 0);
1658 1692
    if (fd == -1)
1659
        rb_sys_fail("socket");
1693
        rb_sys_fail("socket(2)");
1660 1694

  
1661 1695
    bufsize = sizeof(initbuf);
1662 1696
    buf = initbuf;
ext/socket/basicsocket.c (working copy)
80 80
    }
81 81
    GetOpenFile(sock, fptr);
82 82
    if (shutdown(fptr->fd, how) == -1)
83
	rb_sys_fail(0);
83
	rb_sys_fail("shutdown(2)");
84 84

  
85 85
    return INT2FIX(0);
86 86
}
......
247 247
	break;
248 248
    }
249 249

  
250
#define rb_sys_fail_path(path) rb_sys_fail_str(path)
251

  
252 250
    rb_io_check_closed(fptr);
253 251
    if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
254
	rb_sys_fail_path(fptr->pathv);
252
	rsock_sys_fail_path("setsockopt(2)", fptr->pathv);
255 253

  
256 254
    return INT2FIX(0);
257 255
}
......
332 330
    rb_io_check_closed(fptr);
333 331

  
334 332
    if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
335
	rb_sys_fail_path(fptr->pathv);
333
	rsock_sys_fail_path("getsockopt(2)", fptr->pathv);
336 334

  
337 335
    return rsock_sockopt_new(family, level, option, rb_str_new(buf, len));
338 336
}
......
427 425
    gid_t egid;
428 426
    GetOpenFile(self, fptr);
429 427
    if (getpeereid(fptr->fd, &euid, &egid) == -1)
430
	rb_sys_fail("getpeereid");
428
	rb_sys_fail("getpeereid(3)");
431 429
    return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
432 430
#elif defined(SO_PEERCRED) /* GNU/Linux */
433 431
    rb_io_t *fptr;
......
443 441
    VALUE ret;
444 442
    GetOpenFile(self, fptr);
445 443
    if (getpeerucred(fptr->fd, &uc) == -1)
446
	rb_sys_fail("getpeerucred");
444
	rb_sys_fail("getpeerucred(3C)");
447 445
    ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
448 446
    ucred_free(uc);
449 447
    return ret;
ext/socket/unixsocket.c (working copy)
34 34
    SafeStringValue(path);
35 35
    fd = rsock_socket(AF_UNIX, SOCK_STREAM, 0);
36 36
    if (fd < 0) {
37
	rb_sys_fail("socket(2)");
37
	rsock_sys_fail_path("socket(2)", path);
38 38
    }
39 39

  
40 40
    MEMZERO(&sockaddr, struct sockaddr_un, 1);
......
62 62

  
63 63
    if (status < 0) {
64 64
	close(fd);
65
	rb_sys_fail_str(path);
65
	rsock_sys_fail_path("connect(2)", path);
66 66
    }
67 67

  
68 68
    if (server) {
69 69
	if (listen(fd, SOMAXCONN) < 0) {
70 70
	    close(fd);
71
	    rb_sys_fail("listen(2)");
71
	    rsock_sys_fail_path("listen(2)", path);
72 72
	}
73 73
    }
74 74

  
......
117 117
	struct sockaddr_un addr;
118 118
	socklen_t len = (socklen_t)sizeof(addr);
119 119
	if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
120
	    rb_sys_fail(0);
120
	    rsock_sys_fail_path("getsockname(2)", fptr->pathv);
121 121
	fptr->pathv = rb_obj_freeze(rsock_unixpath_str(&addr, len));
122 122
    }
123 123
    return rb_str_dup(fptr->pathv);
......
250 250
    arg.fd = fptr->fd;
251 251
    while ((int)BLOCKING_REGION_FD(sendmsg_blocking, &arg) == -1) {
252 252
	if (!rb_io_wait_writable(arg.fd))
253
	    rb_sys_fail("sendmsg(2)");
253
	    rsock_sys_fail_path("sendmsg(2)", fptr->pathv);
254 254
    }
255 255

  
256 256
    return Qnil;
......
338 338
    arg.fd = fptr->fd;
339 339
    while ((int)BLOCKING_REGION_FD(recvmsg_blocking, &arg) == -1) {
340 340
	if (!rb_io_wait_readable(arg.fd))
341
	    rb_sys_fail("recvmsg(2)");
341
	    rsock_sys_fail_path("recvmsg(2)", fptr->pathv);
342 342
    }
343 343

  
344 344
#if FD_PASSING_BY_MSG_CONTROL
......
424 424
    GetOpenFile(sock, fptr);
425 425

  
426 426
    if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
427
	rb_sys_fail("getsockname(2)");
427
	rsock_sys_fail_path("getsockname(2)", fptr->pathv);
428 428
    return rsock_unixaddr(&addr, len);
429 429
}
430 430

  
......
450 450
    GetOpenFile(sock, fptr);
451 451

  
452 452
    if (getpeername(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
453
	rb_sys_fail("getpeername(2)");
453
	rsock_sys_fail_path("getpeername(2)", fptr->pathv);
454 454
    return rsock_unixaddr(&addr, len);
455 455
}
456 456

  
test/socket/test_tcp.rb (working copy)
6 6

  
7 7

  
8 8
class TestSocket_TCPSocket < Test::Unit::TestCase
9
  def test_initialize_failure
10
    s = TCPServer.new("localhost", nil)
11
    server_port = s.addr[1]
12

  
13
    c = TCPSocket.new("localhost", server_port)
14
    client_port = c.addr[1]
15

  
16
    begin
17
      # TCPServer.new uses SO_REUSEADDR so we must create a failure on the
18
      # local address.
19
      TCPSocket.new("localhost", server_port, "localhost", client_port)
20
      flunk "expected SystemCallError"
21
    rescue SystemCallError => e
22
      assert_match "for \"localhost\" port #{client_port}", e.message
23
    end
24
  end
25

  
9 26
  def test_recvfrom
10 27
    svr = TCPServer.new("localhost", 0)
11 28
    th = Thread.new {
test/socket/test_socket.rb (working copy)
70 70
    }
71 71
  end
72 72

  
73
  def test_bind
74
    Socket.open(Socket::AF_INET, Socket::SOCK_STREAM, 0) {|bound|
75
      bound.bind(Socket.sockaddr_in(0, "127.0.0.1"))
76
      addr = bound.getsockname
77
      port, = Socket.unpack_sockaddr_in(addr)
78

  
79
      Socket.open(Socket::AF_INET, Socket::SOCK_STREAM, 0) {|s|
80
        e = assert_raises(Errno::EADDRINUSE) do
81
          s.bind(Socket.sockaddr_in(port, "127.0.0.1"))
82
        end
83

  
84
        assert_match "bind(2) for \"127.0.0.1\" port #{port}", e.message
85
      }
86
    }
87
  end
88

  
73 89
  def test_getaddrinfo
74 90
    # This should not send a DNS query because AF_UNIX.
75 91
    assert_raise(SocketError) { Socket.getaddrinfo("www.kame.net", 80, "AF_UNIX") }
test/socket/test_udp.rb (working copy)
36 36
      s.bind(host, 2000)
37 37
    }
38 38
  end
39

  
40
  def test_bind_addrinuse
41
    host = "127.0.0.1"
42
    port = 2001
43

  
44
    in_use = UDPSocket.new
45
    in_use.bind(host, port)
46

  
47
    s = UDPSocket.new
48
    
49
    e = assert_raises(Errno::EADDRINUSE) do
50
      s.bind(host, port)
51
    end
52

  
53
    assert_match "bind(2) for \"#{host}\" port #{port}", e.message
54
  end
55

  
56
  def test_send_too_long
57
    u = UDPSocket.new
58

  
59
    e = assert_raises Errno::EMSGSIZE do
60
      u.send "\0" * 100_000, 0, "127.0.0.1", 7 # echo
61
    end
62

  
63
    assert_match 'for "127.0.0.1" port 7', e.message
64
  end
39 65
end if defined?(UDPSocket)