[#108552] [Ruby master Bug#18782] Race conditions in autoload when loading the same feature with multiple threads. — "ioquatix (Samuel Williams)" <noreply@...>
Issue #18782 has been reported by ioquatix (Samuel Williams).
11 messages
2022/05/14
[ruby-core:108678] [Ruby master Bug#18791] Unexpected behavior of Socket#connect_nonblock
From:
"jeremyevans0 (Jeremy Evans)" <noreply@...>
Date:
2022-05-24 19:51:55 UTC
List:
ruby-core #108678
Issue #18791 has been updated by jeremyevans0 (Jeremy Evans).
Status changed from Open to Rejected
This doesn't look like a bug. If the `connect` system call returns `0`, then you were able to connect, and `connect_nonblock` in Ruby returns `0` as well. Yes, you should treat `0` as indicating the connection was successful. The documentation states `Returns 0 if successful, otherwise an exception is raised.` I think that explains the behavior correctly, so this does not appear to be a documentation bug either.
I think maybe you are expecting `Errno::EISCONN` must be raised to indicate a successful connection. That would also indicate a successful connection, but having the method return `0` also indicates the connection was successful. The example code is written so either returning `0` or raising `Errno::EISCONN` is treated as a successful connection, so the example code does not appear to be incorrect.
----------------------------------------
Bug #18791: Unexpected behavior of Socket#connect_nonblock
https://bugs.ruby-lang.org/issues/18791#change-97719
* Author: midnight (Sarun R)
* Status: Rejected
* Priority: Normal
* ruby -v: ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [x86_64-linux]
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
I followed an example of [Socket#connect_nonblock](https://ruby-doc.org/stdlib-3.1.2/libdoc/socket/rdoc/Socket.html#method-i-connect_nonblock) on the document.
Waiting for multiple Socket connections at once.
~~~Ruby
# 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.
~~~C
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.
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>