summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKJ Tsanaktsidis <[email protected]>2024-01-22 12:06:03 +1100
committerKJ Tsanaktsidis <[email protected]>2024-01-22 14:34:31 +1100
commit6c0e58a54e3fda604386d9c409e2a9998bbc9352 ()
tree653b9271c7182c83bfb7fe4d6e87e74ab4334cc4
parentce5e7629b57904c34a529372f365e04d4f9abb06 (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.c25
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;
}