diff options
| author | Misaki Shioi <31817032+shioimm@users.noreply.github.com> | 2025-12-19 15:44:35 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-19 15:44:35 +0900 |
| commit | 47244b0f306161f175b21f74d801882e950e18be (patch) | |
| tree | 765af248b9f1acc1d8af4fbfa4f6d58eb04833f4 /ext | |
| parent | f81c62be3df7b29c4c3b6adaa16599b38d0c0c46 (diff) | |
Fix: Specifying 0 should cause an immediate timeout (#15641)
This change fixes a bug in which specifying 0 for timeout-related options (such as the `timeout` option of `Addrinfo.getaddrinfo`) incorrectly results in an infinite wait.
(This change overwrites https://github.com/ruby/ruby/pull/15626 .)
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/socket/ipsocket.c | 27 | ||||
| -rw-r--r-- | ext/socket/raddrinfo.c | 29 | ||||
| -rw-r--r-- | ext/socket/rubysocket.h | 5 | ||||
| -rw-r--r-- | ext/socket/socket.c | 8 | ||||
| -rw-r--r-- | ext/socket/tcpsocket.c | 2 | ||||
| -rw-r--r-- | ext/socket/udpsocket.c | 6 |
6 files changed, 31 insertions, 46 deletions
diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c index c9fcfb64fb..e952b7871b 100644 --- a/ext/socket/ipsocket.c +++ b/ext/socket/ipsocket.c @@ -83,15 +83,13 @@ init_inetsock_internal(VALUE v) VALUE open_timeout = arg->open_timeout; VALUE timeout; VALUE starts_at; - unsigned int timeout_msec; timeout = NIL_P(open_timeout) ? resolv_timeout : open_timeout; - timeout_msec = NIL_P(timeout) ? 0 : rsock_value_timeout_to_msec(timeout); starts_at = current_clocktime(); arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv, family, SOCK_STREAM, - (type == INET_SERVER) ? AI_PASSIVE : 0, timeout_msec); + (type == INET_SERVER) ? AI_PASSIVE : 0, timeout); /* * Maybe also accept a local address @@ -99,7 +97,7 @@ init_inetsock_internal(VALUE v) if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) { arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv, - family, SOCK_STREAM, 0, 0); + family, SOCK_STREAM, 0, timeout); } VALUE io = Qnil; @@ -630,14 +628,7 @@ init_fast_fallback_inetsock_internal(VALUE v) arg->getaddrinfo_shared = NULL; int family = arg->families[0]; - unsigned int t; - if (!NIL_P(open_timeout)) { - t = rsock_value_timeout_to_msec(open_timeout); - } else if (!NIL_P(resolv_timeout)) { - t = rsock_value_timeout_to_msec(resolv_timeout); - } else { - t = 0; - } + VALUE t = NIL_P(open_timeout) ? resolv_timeout : open_timeout; arg->remote.res = rsock_addrinfo( arg->remote.host, @@ -1337,15 +1328,7 @@ rsock_init_inetsock( * Maybe also accept a local address */ if (!NIL_P(local_host) || !NIL_P(local_serv)) { - unsigned int t; - if (!NIL_P(open_timeout)) { - t = rsock_value_timeout_to_msec(open_timeout); - } else if (!NIL_P(resolv_timeout)) { - t = rsock_value_timeout_to_msec(resolv_timeout); - } else { - t = 0; - } - + VALUE t = NIL_P(open_timeout) ? resolv_timeout : open_timeout; local_res = rsock_addrinfo( local_host, local_serv, @@ -1609,7 +1592,7 @@ static VALUE ip_s_getaddress(VALUE obj, VALUE host) { union_sockaddr addr; - struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, 0, 0); + struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, 0, Qnil); socklen_t len = res->ai->ai_addrlen; /* just take the first one */ diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index 3dcbe7717a..6cdf5c6abc 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -293,7 +293,7 @@ rb_freeaddrinfo(struct rb_addrinfo *ai) xfree(ai); } -unsigned int +static int rsock_value_timeout_to_msec(VALUE timeout) { double seconds = NUM2DBL(timeout); @@ -308,7 +308,7 @@ rsock_value_timeout_to_msec(VALUE timeout) #if GETADDRINFO_IMPL == 0 static int -rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, unsigned int _timeout) +rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int _timeout) { return getaddrinfo(hostp, portp, hints, ai); } @@ -346,7 +346,7 @@ fork_safe_getaddrinfo(void *arg) } static int -rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, unsigned int _timeout) +rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int _timeout) { struct getaddrinfo_arg arg; MEMZERO(&arg, struct getaddrinfo_arg, 1); @@ -367,11 +367,11 @@ struct getaddrinfo_arg int err, gai_errno, refcount, done, cancelled, timedout; rb_nativethread_lock_t lock; rb_nativethread_cond_t cond; - unsigned int timeout; + int timeout; }; static struct getaddrinfo_arg * -allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addrinfo *hints, unsigned int timeout) +allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addrinfo *hints, int timeout) { size_t hostp_offset = sizeof(struct getaddrinfo_arg); size_t portp_offset = hostp_offset + (hostp ? strlen(hostp) + 1 : 0); @@ -465,8 +465,11 @@ wait_getaddrinfo(void *ptr) struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr; rb_nativethread_lock_lock(&arg->lock); while (!arg->done && !arg->cancelled) { - unsigned long msec = arg->timeout; - if (msec > 0) { + long msec = arg->timeout; + if (msec == 0) { + arg->cancelled = 1; + arg->timedout = 1; + } else if (msec > 0) { rb_native_cond_timedwait(&arg->cond, &arg->lock, msec); if (!arg->done) { arg->cancelled = 1; @@ -549,7 +552,7 @@ fork_safe_do_getaddrinfo(void *ptr) } static int -rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, unsigned int timeout) +rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int timeout) { int retry; struct getaddrinfo_arg *arg; @@ -1021,7 +1024,7 @@ rb_scheduler_getaddrinfo(VALUE scheduler, VALUE host, const char *service, } struct rb_addrinfo* -rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, unsigned int timeout) +rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout) { struct rb_addrinfo* res = NULL; struct addrinfo *ai; @@ -1056,7 +1059,8 @@ rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_h } if (!resolved) { - error = rb_getaddrinfo(hostp, portp, hints, &ai, timeout); + int t = NIL_P(timeout) ? -1 : rsock_value_timeout_to_msec(timeout); + error = rb_getaddrinfo(hostp, portp, hints, &ai, t); if (error == 0) { res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); res->allocated_by_malloc = 0; @@ -1089,7 +1093,7 @@ rsock_fd_family(int fd) } struct rb_addrinfo* -rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, unsigned int timeout) +rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, VALUE timeout) { struct addrinfo hints; @@ -1380,8 +1384,7 @@ call_getaddrinfo(VALUE node, VALUE service, hints.ai_flags = NUM2INT(flags); } - unsigned int t = NIL_P(timeout) ? 0 : rsock_value_timeout_to_msec(timeout); - res = rsock_getaddrinfo(node, service, &hints, socktype_hack, t); + res = rsock_getaddrinfo(node, service, &hints, socktype_hack, timeout); if (res == NULL) rb_raise(rb_eSocket, "host not found"); diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index 638b7ede6e..2ec3ab335a 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -327,8 +327,8 @@ void rb_freeaddrinfo(struct rb_addrinfo *ai); VALUE rsock_freeaddrinfo(VALUE arg); int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); int rsock_fd_family(int fd); -struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, unsigned int timeout); -struct rb_addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, unsigned int timeout); +struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, VALUE timeout); +struct rb_addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout); VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len); VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len); @@ -453,7 +453,6 @@ void free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shar # endif #endif -unsigned int rsock_value_timeout_to_msec(VALUE); NORETURN(void rsock_raise_user_specified_timeout(struct addrinfo *ai, VALUE host, VALUE port)); void rsock_init_basicsocket(void); diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 26bf0bae8c..a8e5ae8119 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -965,7 +965,7 @@ sock_s_gethostbyname(VALUE obj, VALUE host) { rb_warn("Socket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead."); struct rb_addrinfo *res = - rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, 0); + rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, Qnil); return rsock_make_hostent(host, res, sock_sockaddr); } @@ -1183,7 +1183,7 @@ sock_s_getaddrinfo(int argc, VALUE *argv, VALUE _) norevlookup = rsock_do_not_reverse_lookup; } - res = rsock_getaddrinfo(host, port, &hints, 0, 0); + res = rsock_getaddrinfo(host, port, &hints, 0, Qnil); ret = make_addrinfo(res, norevlookup); rb_freeaddrinfo(res); @@ -1279,7 +1279,7 @@ sock_s_getnameinfo(int argc, VALUE *argv, VALUE _) hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM; /* af */ hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af); - res = rsock_getaddrinfo(host, port, &hints, 0, 0); + res = rsock_getaddrinfo(host, port, &hints, 0, Qnil); sap = res->ai->ai_addr; salen = res->ai->ai_addrlen; } @@ -1335,7 +1335,7 @@ sock_s_getnameinfo(int argc, VALUE *argv, VALUE _) static VALUE sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host) { - struct rb_addrinfo *res = rsock_addrinfo(host, port, AF_UNSPEC, 0, 0, 0); + struct rb_addrinfo *res = rsock_addrinfo(host, port, AF_UNSPEC, 0, 0, Qnil); VALUE addr = rb_str_new((char*)res->ai->ai_addr, res->ai->ai_addrlen); rb_freeaddrinfo(res); diff --git a/ext/socket/tcpsocket.c b/ext/socket/tcpsocket.c index 300a426eda..7ce536e0af 100644 --- a/ext/socket/tcpsocket.c +++ b/ext/socket/tcpsocket.c @@ -113,7 +113,7 @@ tcp_s_gethostbyname(VALUE obj, VALUE host) { rb_warn("TCPSocket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead."); struct rb_addrinfo *res = - rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, 0); + rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, Qnil); return rsock_make_hostent(host, res, tcp_sockaddr); } diff --git a/ext/socket/udpsocket.c b/ext/socket/udpsocket.c index 5538f24523..b2bc925538 100644 --- a/ext/socket/udpsocket.c +++ b/ext/socket/udpsocket.c @@ -84,7 +84,7 @@ udp_connect(VALUE self, VALUE host, VALUE port) { struct udp_arg arg = {.io = self}; - arg.res = rsock_addrinfo(host, port, rsock_fd_family(rb_io_descriptor(self)), SOCK_DGRAM, 0, 0); + arg.res = rsock_addrinfo(host, port, rsock_fd_family(rb_io_descriptor(self)), SOCK_DGRAM, 0, Qnil); int result = (int)rb_ensure(udp_connect_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res); if (!result) { @@ -129,7 +129,7 @@ udp_bind(VALUE self, VALUE host, VALUE port) { struct udp_arg arg = {.io = self}; - arg.res = rsock_addrinfo(host, port, rsock_fd_family(rb_io_descriptor(self)), SOCK_DGRAM, 0, 0); + arg.res = rsock_addrinfo(host, port, rsock_fd_family(rb_io_descriptor(self)), SOCK_DGRAM, 0, Qnil); VALUE result = rb_ensure(udp_bind_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res); if (!result) { @@ -212,7 +212,7 @@ udp_send(int argc, VALUE *argv, VALUE sock) GetOpenFile(sock, arg.fptr); arg.sarg.fd = arg.fptr->fd; arg.sarg.flags = NUM2INT(flags); - arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0, 0); + arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0, Qnil); ret = rb_ensure(udp_send_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res); if (!ret) rsock_sys_fail_host_port("sendto(2)", host, port); |
