diff options
author | KJ Tsanaktsidis <[email protected]> | 2024-01-22 12:06:03 +1100 |
---|---|---|
committer | KJ Tsanaktsidis <[email protected]> | 2024-01-22 14:34:31 +1100 |
commit | 6c0e58a54e3fda604386d9c409e2a9998bbc9352 () | |
tree | 653b9271c7182c83bfb7fe4d6e87e74ab4334cc4 | |
parent | ce5e7629b57904c34a529372f365e04d4f9abb06 (diff) |
Make sure the correct error is raised for EAI_SYSTEM resolver fail
In case of EAI_SYSTEM, getaddrinfo is supposed to set more detail in errno; however, because we call getaddrinfo on a thread now, and errno is threadlocal, that information is being lost. Instead, we just raise whatever errno happens to be on the calling thread (which can be something very confusing, like `ECHILD`). Fix it by explicitly propagating errno back to the calling thread through the getaddrinfo_arg structure. [Bug #20198]
-rw-r--r-- | ext/socket/raddrinfo.c | 25 |
1 files changed, 19 insertions, 6 deletions
@@ -345,7 +345,7 @@ struct getaddrinfo_arg char *node, *service; struct addrinfo hints; struct addrinfo *ai; - int err, refcount, done, cancelled; rb_nativethread_lock_t lock; rb_nativethread_cond_t cond; }; @@ -406,8 +406,9 @@ do_getaddrinfo(void *ptr) { struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr; - int err; err = getaddrinfo(arg->node, arg->service, &arg->hints, &arg->ai); #ifdef __linux__ /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420] @@ -420,6 +421,7 @@ do_getaddrinfo(void *ptr) rb_nativethread_lock_lock(&arg->lock); { arg->err = err; if (arg->cancelled) { freeaddrinfo(arg->ai); } @@ -479,7 +481,7 @@ rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hint { int retry; struct getaddrinfo_arg *arg; - int err; start: retry = 0; @@ -503,6 +505,7 @@ start: { if (arg->done) { err = arg->err; if (err == 0) *ai = arg->ai; } else if (arg->cancelled) { @@ -525,6 +528,10 @@ start: rb_thread_check_ints(); if (retry) goto start; return err; } @@ -591,7 +598,7 @@ struct getnameinfo_arg size_t hostlen; char *serv; size_t servlen; - int err, refcount, done, cancelled; rb_nativethread_lock_t lock; rb_nativethread_cond_t cond; }; @@ -644,12 +651,14 @@ do_getnameinfo(void *ptr) { struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr; - int err; err = getnameinfo(arg->sa, arg->salen, arg->host, (socklen_t)arg->hostlen, arg->serv, (socklen_t)arg->servlen, arg->flags); int need_free = 0; rb_nativethread_lock_lock(&arg->lock); arg->err = err; if (!arg->cancelled) { arg->done = 1; rb_native_cond_signal(&arg->cond); @@ -691,7 +700,7 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, { int retry; struct getnameinfo_arg *arg; - int err; start: retry = 0; @@ -714,6 +723,7 @@ start: rb_nativethread_lock_lock(&arg->lock); if (arg->done) { err = arg->err; if (err == 0) { if (host) memcpy(host, arg->host, hostlen); if (serv) memcpy(serv, arg->serv, servlen); @@ -738,6 +748,9 @@ start: rb_thread_check_ints(); if (retry) goto start; return err; } |