Actions
Bug #18791
closedUnexpected behavior of Socket#connect_nonblock
Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [x86_64-linux]
Description
I followed an example of Socket#connect_nonblock on the document.
Waiting for multiple Socket connections at once.
# Pull down Google's web page
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(80, 'www.google.com')
begin # emulate blocking connect
socket.connect_nonblock(sockaddr)
rescue IO::WaitWritable
IO.select(nil, [socket]) # wait 3-way handshake completion
begin
# ****************** The problem is here ********************
socket.connect_nonblock(sockaddr) # check connection failure
rescue Errno::EISCONN
end
end
socket.write("GET / HTTP/1.0\r\n\r\n")
results = socket.read
The first call to connect_nonblock
raises IO::WaitWritable
as expected.
But the confirmation call did not raise Errno::EISCONN
; instead, it returned 0
.
Upon source code inspection, 0 was returned from connect
and is supposed to mean success.
static VALUE
sock_connect_nonblock(VALUE sock, VALUE addr, VALUE ex)
{
VALUE rai;
rb_io_t *fptr;
int n;
SockAddrStringValueWithAddrinfo(addr, rai);
addr = rb_str_new4(addr);
GetOpenFile(sock, fptr);
rb_io_set_nonblock(fptr);
n = connect(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr));
if (n < 0) {
int e = errno;
if (e == EINPROGRESS) {
if (ex == Qfalse) {
return sym_wait_writable;
}
rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "connect(2) would block");
}
if (e == EISCONN) {
if (ex == Qfalse) {
return INT2FIX(0);
}
}
rsock_syserr_fail_raddrinfo_or_sockaddr(e, "connect(2)", addr, rai);
}
return INT2FIX(n);
}
I made sure ex
is true
, so it is not return INT2FIX(0);
that get returned but the last statement return INT2FIX(n);
.
Is this the intended behavior? It does surprise me and clearly doesn't explain very well in the document.
The example shown implied that the only way to confirm the connection is Errno::EISCONN
; never mention the return code.
Actions
Like0
Like0Like0Like0Like0