mirror of
https://github.com/ruby/ruby.git
synced 2026-01-26 12:14:51 +00:00
Add host information to timeout error messages in TCPSocket.new and Socket.tcp (#15582)
This change adds host information to the error messages shown when a timeout occurs while passing timeout options to `TCPSocket.new` or `Socket.tcp`, for improved usability. (When the `fast_fallback option` is enabled, there may be multiple possible destinations, so the host name is shown instead of an IP address.) As part of this change, the error messages in `Addrinfo.getaddrinfo` and `Addrinfo#connect_internal`, both of which are used by `Socket.tcp`, have also been improved in the same way.
This commit is contained in:
parent
1506c489ee
commit
54d3945ee5
Notes:
git
2025-12-17 07:16:59 +00:00
Merged-By: shioimm <shioi.mm@gmail.com>
@ -473,7 +473,7 @@ rsock_socket(int domain, int type, int proto)
|
||||
|
||||
/* emulate blocking connect behavior on EINTR or non-blocking socket */
|
||||
static int
|
||||
wait_connectable(VALUE self, VALUE timeout)
|
||||
wait_connectable(VALUE self, VALUE timeout, const struct sockaddr *sockaddr, int len)
|
||||
{
|
||||
int sockerr;
|
||||
socklen_t sockerrlen;
|
||||
@ -514,7 +514,10 @@ wait_connectable(VALUE self, VALUE timeout)
|
||||
VALUE result = rb_io_wait(self, RB_INT2NUM(RUBY_IO_READABLE|RUBY_IO_WRITABLE), timeout);
|
||||
|
||||
if (result == Qfalse) {
|
||||
rb_raise(rb_eIOTimeoutError, "Connect timed out!");
|
||||
VALUE rai = rsock_addrinfo_new((struct sockaddr *)sockaddr, len, PF_UNSPEC, 0, 0, Qnil, Qnil);
|
||||
VALUE addr_str = rsock_addrinfo_inspect_sockaddr(rai);
|
||||
VALUE message = rb_sprintf("user specified timeout for %" PRIsVALUE, addr_str);
|
||||
rb_raise(rb_eIOTimeoutError, "%" PRIsVALUE, message);
|
||||
}
|
||||
|
||||
int revents = RB_NUM2INT(result);
|
||||
@ -603,7 +606,7 @@ rsock_connect(VALUE self, const struct sockaddr *sockaddr, int len, int socks, V
|
||||
#ifdef EINPROGRESS
|
||||
case EINPROGRESS:
|
||||
#endif
|
||||
return wait_connectable(self, timeout);
|
||||
return wait_connectable(self, timeout, sockaddr, len);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
|
||||
@ -27,9 +27,19 @@ struct inetsock_arg
|
||||
};
|
||||
|
||||
void
|
||||
rsock_raise_user_specified_timeout(void)
|
||||
rsock_raise_user_specified_timeout(struct addrinfo *ai, VALUE host, VALUE port)
|
||||
{
|
||||
rb_raise(rb_eIOTimeoutError, "user specified timeout");
|
||||
VALUE message;
|
||||
|
||||
if (ai && ai->ai_addr) {
|
||||
VALUE rai = rsock_addrinfo_new((struct sockaddr *)ai->ai_addr, (socklen_t)ai->ai_addrlen, PF_UNSPEC, 0, 0, Qnil, Qnil);
|
||||
VALUE addr_str = rsock_addrinfo_inspect_sockaddr(rai);
|
||||
message = rb_sprintf("user specified timeout for %" PRIsVALUE, addr_str);
|
||||
} else {
|
||||
message = rb_sprintf("user specified timeout for %" PRIsVALUE " port %" PRIsVALUE, host, port);
|
||||
}
|
||||
|
||||
rb_raise(rb_eIOTimeoutError, "%" PRIsVALUE, message);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
@ -149,7 +159,9 @@ init_inetsock_internal(VALUE v)
|
||||
} else {
|
||||
VALUE elapsed = rb_funcall(current_clocktime(), '-', 1, starts_at);
|
||||
timeout = rb_funcall(open_timeout, '-', 1, elapsed);
|
||||
if (rb_funcall(timeout, '<', 1, INT2FIX(0)) == Qtrue) rsock_raise_user_specified_timeout();
|
||||
if (rb_funcall(timeout, '<', 1, INT2FIX(0)) == Qtrue) {
|
||||
rsock_raise_user_specified_timeout(res, arg->remote.host, arg->remote.serv);
|
||||
}
|
||||
}
|
||||
|
||||
if (status >= 0) {
|
||||
@ -844,6 +856,10 @@ init_fast_fallback_inetsock_internal(VALUE v)
|
||||
if (!NIL_P(open_timeout)) {
|
||||
VALUE elapsed = rb_funcall(current_clocktime(), '-', 1, starts_at);
|
||||
timeout = rb_funcall(open_timeout, '-', 1, elapsed);
|
||||
|
||||
if (rb_funcall(timeout, '<', 1, INT2FIX(0)) == Qtrue) {
|
||||
rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv);
|
||||
}
|
||||
}
|
||||
if (NIL_P(timeout)) {
|
||||
if (!NIL_P(connect_timeout)) {
|
||||
@ -1180,7 +1196,9 @@ init_fast_fallback_inetsock_internal(VALUE v)
|
||||
}
|
||||
}
|
||||
|
||||
if (is_timeout_tv(user_specified_open_timeout_at, now)) rsock_raise_user_specified_timeout();
|
||||
if (is_timeout_tv(user_specified_open_timeout_at, now)) {
|
||||
rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv);
|
||||
}
|
||||
|
||||
if (!any_addrinfos(&resolution_store)) {
|
||||
if (!in_progress_fds(arg->connection_attempt_fds_size) &&
|
||||
@ -1203,7 +1221,7 @@ init_fast_fallback_inetsock_internal(VALUE v)
|
||||
resolution_store.is_all_finished) &&
|
||||
(is_timeout_tv(user_specified_connect_timeout_at, now) ||
|
||||
!in_progress_fds(arg->connection_attempt_fds_size))) {
|
||||
rsock_raise_user_specified_timeout();
|
||||
rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ class Addrinfo
|
||||
break
|
||||
when :wait_writable
|
||||
sock.wait_writable(timeout) or
|
||||
raise Errno::ETIMEDOUT, 'user specified timeout'
|
||||
raise Errno::ETIMEDOUT, "user specified timeout for #{self.ip_address}:#{self.ip_port}"
|
||||
end while true
|
||||
else
|
||||
sock.connect(self)
|
||||
@ -905,7 +905,9 @@ class Socket < BasicSocket
|
||||
end
|
||||
end
|
||||
|
||||
raise(IO::TimeoutError, 'user specified timeout') if expired?(now, user_specified_open_timeout_at)
|
||||
if expired?(now, user_specified_open_timeout_at)
|
||||
raise(IO::TimeoutError, "user specified timeout for #{host}:#{port}")
|
||||
end
|
||||
|
||||
if resolution_store.empty_addrinfos?
|
||||
if connecting_sockets.empty? && resolution_store.resolved_all_families?
|
||||
@ -918,7 +920,7 @@ class Socket < BasicSocket
|
||||
|
||||
if (expired?(now, user_specified_resolv_timeout_at) || resolution_store.resolved_all_families?) &&
|
||||
(expired?(now, user_specified_connect_timeout_at) || connecting_sockets.empty?)
|
||||
raise IO::TimeoutError, 'user specified timeout'
|
||||
raise(IO::TimeoutError, "user specified timeout for #{host}:#{port}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -597,7 +597,15 @@ start:
|
||||
|
||||
if (need_free) free_getaddrinfo_arg(arg);
|
||||
|
||||
if (timedout) rsock_raise_user_specified_timeout();
|
||||
if (timedout) {
|
||||
if (arg->ai) {
|
||||
rsock_raise_user_specified_timeout(arg->ai, Qnil, Qnil);
|
||||
} else {
|
||||
VALUE host = rb_str_new_cstr(hostp);
|
||||
VALUE port = rb_str_new_cstr(portp);
|
||||
rsock_raise_user_specified_timeout(NULL, host, port);
|
||||
}
|
||||
}
|
||||
|
||||
// If the current thread is interrupted by asynchronous exception, the following raises the exception.
|
||||
// But if the current thread is interrupted by timer thread, the following returns; we need to manually retry.
|
||||
|
||||
@ -454,7 +454,7 @@ void free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shar
|
||||
#endif
|
||||
|
||||
unsigned int rsock_value_timeout_to_msec(VALUE);
|
||||
NORETURN(void rsock_raise_user_specified_timeout(void));
|
||||
NORETURN(void rsock_raise_user_specified_timeout(struct addrinfo *ai, VALUE host, VALUE port));
|
||||
|
||||
void rsock_init_basicsocket(void);
|
||||
void rsock_init_ipsocket(void);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user