ruby-changes:63989
From: Masaki <ko1@a...>
Date: Mon, 7 Dec 2020 13:34:21 +0900 (JST)
Subject: [ruby-changes:63989] 5d8bcc4870 (master): Revert getaddrinfo_a()
https://git.ruby-lang.org/ruby.git/commit/?id=5d8bcc4870 From 5d8bcc4870601ab1ee05346346f241d4a805aac9 Mon Sep 17 00:00:00 2001 From: Masaki Matsushita <glass.saga@g...> Date: Mon, 7 Dec 2020 12:49:44 +0900 Subject: Revert getaddrinfo_a() getaddrinfo_a() gets stuck after fork(). To avoid this, we need 1 second sleep to wait for internal worker threads of getaddrinfo_a() to be finished, but that is unacceptable. [Bug #17220] [Feature #17134] [Feature #17187] diff --git a/configure.ac b/configure.ac index 84680cb..6c6d73f 100644 --- a/configure.ac +++ b/configure.ac @@ -1152,7 +1152,6 @@ AC_CHECK_LIB(crypt, crypt) # glibc (GNU/Linux, GNU/Hurd, GNU/kFreeBSD) https://github.com/ruby/ruby/blob/trunk/configure.ac#L1152 AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX AC_CHECK_LIB(socket, shutdown) # SunOS/Solaris -AC_CHECK_LIB(anl, getaddrinfo_a) dnl Checks for header files. AC_HEADER_DIRENT @@ -1944,7 +1943,6 @@ AC_CHECK_FUNCS(fsync) https://github.com/ruby/ruby/blob/trunk/configure.ac#L1943 AC_CHECK_FUNCS(ftruncate) AC_CHECK_FUNCS(ftruncate64) # used for Win32 platform AC_CHECK_FUNCS(getattrlist) -AC_CHECK_FUNCS(getaddrinfo_a) AC_CHECK_FUNCS(getcwd) AC_CHECK_FUNCS(getgidx) AC_CHECK_FUNCS(getgrnam) diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb index 1a67e00..c86cc8f 100644 --- a/ext/socket/extconf.rb +++ b/ext/socket/extconf.rb @@ -444,7 +444,6 @@ else https://github.com/ruby/ruby/blob/trunk/ext/socket/extconf.rb#L444 test_func = "socket(0,0,0)" have_library("nsl", 't_open("", 0, (struct t_info *)NULL)', headers) # SunOS have_library("socket", "socket(0,0,0)", headers) # SunOS - have_library("anl", 'getaddrinfo_a', headers) end if have_func(test_func, headers) @@ -506,7 +505,6 @@ EOF https://github.com/ruby/ruby/blob/trunk/ext/socket/extconf.rb#L505 unless have_func("gethostname((char *)0, 0)", headers) have_func("uname((struct utsname *)NULL)", headers) end - have_func("getaddrinfo_a", headers) ipv6 = false default_ipv6 = /haiku/ !~ RUBY_PLATFORM diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c index 96782c7..646bc7c 100644 --- a/ext/socket/ipsocket.c +++ b/ext/socket/ipsocket.c @@ -51,16 +51,9 @@ init_inetsock_internal(VALUE v) https://github.com/ruby/ruby/blob/trunk/ext/socket/ipsocket.c#L51 int family = AF_UNSPEC; const char *syscall = 0; -#ifdef HAVE_GETADDRINFO_A - arg->remote.res = rsock_addrinfo_a(arg->remote.host, arg->remote.serv, - family, SOCK_STREAM, - (type == INET_SERVER) ? AI_PASSIVE : 0, - arg->resolv_timeout); -#else arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv, family, SOCK_STREAM, (type == INET_SERVER) ? AI_PASSIVE : 0); -#endif /* diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index c0cc0f3..a3e7e38 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -199,27 +199,6 @@ nogvl_getaddrinfo(void *arg) https://github.com/ruby/ruby/blob/trunk/ext/socket/raddrinfo.c#L199 } #endif -#ifdef HAVE_GETADDRINFO_A -struct gai_suspend_arg -{ - struct gaicb *req; - struct timespec *timeout; -}; - -static void * -nogvl_gai_suspend(void *arg) -{ - int ret; - struct gai_suspend_arg *ptr = arg; - struct gaicb const *wait_reqs[1]; - - wait_reqs[0] = ptr->req; - ret = gai_suspend(wait_reqs, 1, ptr->timeout); - - return (void *)(VALUE)ret; -} -#endif - static int numeric_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, @@ -339,175 +318,6 @@ rb_getaddrinfo(const char *node, const char *service, https://github.com/ruby/ruby/blob/trunk/ext/socket/raddrinfo.c#L318 return ret; } -#ifdef HAVE_GETADDRINFO_A -struct gaicbs { - struct gaicbs *next; - struct gaicb *gaicb; -}; - -/* linked list to retain all outstanding and ongoing requests */ -static struct gaicbs *requests = NULL; - -static void -gaicbs_add(struct gaicb *req) -{ - struct gaicbs *request; - - if (!req) return; - request = (struct gaicbs *)xmalloc(sizeof(struct gaicbs)); - request->gaicb = req; - request->next = requests; - - requests = request; -} - -static void -gaicbs_remove(struct gaicb *req) -{ - struct gaicbs *request = requests; - struct gaicbs *prev = NULL; - - if (!req) return; - - while (request) { - if (request->gaicb == req) break; - prev = request; - request = request->next; - } - - if (request) { - if (prev) { - prev->next = request->next; - } else { - requests = request->next; - } - xfree(request); - } -} - -static void -gaicbs_cancel_all(void) -{ - struct gaicbs *request = requests; - struct gaicbs *tmp, *prev = NULL; - int ret; - - while (request) { - ret = gai_cancel(request->gaicb); - if (ret == EAI_NOTCANCELED) { - // continue to next request - prev = request; - request = request->next; - } else { - // remove the request from the list - if (prev) { - prev->next = request->next; - } else { - requests = request->next; - } - tmp = request; - request = request->next; - xfree(tmp); - } - } -} - -static void -gaicbs_wait_all(void) -{ - struct gaicbs *request = requests; - int size = 0; - - // count gaicbs - while (request) { - size++; - request = request->next; - } - - // create list to wait - const struct gaicb *reqs[size]; - request = requests; - for (int i=0; request; i++) { - reqs[i] = request->gaicb; - request = request->next; - } - - // wait requests - gai_suspend(reqs, size, NULL); // ignore result intentionally -} - -#define MILLISECOND_IN_NANOSECONDS 1000000 - -/* A mitigation for [Bug #17220]. - It cancels all outstanding requests and waits for ongoing requests. - Then, it waits internal worker threads in getaddrinfo_a(3) to be finished. */ -void -rb_getaddrinfo_a_before_fork(void) -{ - gaicbs_cancel_all(); - gaicbs_wait_all(); - - /* wait worker threads in getaddrinfo_a(3) to be finished. - they will finish after 1 second sleep. */ - struct timespec ts = {1, 500 * MILLISECOND_IN_NANOSECONDS}; - nanosleep(&ts, NULL); -} - -int -rb_getaddrinfo_a(const char *node, const char *service, - const struct addrinfo *hints, - struct rb_addrinfo **res, struct timespec *timeout) -{ - struct addrinfo *ai; - int ret; - int allocated_by_malloc = 0; - - ret = numeric_getaddrinfo(node, service, hints, &ai); - if (ret == 0) - allocated_by_malloc = 1; - else { - struct gai_suspend_arg arg; - struct gaicb *reqs[1]; - struct gaicb req; - - req.ar_name = node; - req.ar_service = service; - req.ar_request = hints; - - reqs[0] = &req; - ret = getaddrinfo_a(GAI_NOWAIT, reqs, 1, NULL); - if (ret) return ret; - gaicbs_add(&req); - - arg.req = &req; - arg.timeout = timeout; - - ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_gai_suspend, &arg, RUBY_UBF_IO, 0); - gaicbs_remove(&req); - if (ret && ret != EAI_ALLDONE) { - /* EAI_ALLDONE indicates that the request already completed and gai_suspend was redundant */ - /* on Ubuntu 18.04 (or other systems), gai_suspend(3) returns EAI_SYSTEM/ENOENT on timeout */ - if (ret == EAI_SYSTEM && errno == ENOENT) { - return EAI_AGAIN; - } else { - return ret; - } - } - - - ret = gai_error(reqs[0]); - ai = reqs[0]->ar_result; - } - - if (ret == 0) { - *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); - (*res)->allocated_by_malloc = allocated_by_malloc; - (*res)->ai = ai; - } - return ret; -} -#endif - void rb_freeaddrinfo(struct rb_addrinfo *ai) { @@ -716,42 +526,6 @@ rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_h https://github.com/ruby/ruby/blob/trunk/ext/socket/raddrinfo.c#L526 return res; } -#ifdef HAVE_GETADDRINFO_A -struct rb_addrinfo* -rsock_getaddrinfo_a(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout) -{ - struct rb_addrinfo* res = NULL; - char *hostp, *portp; - int error; - char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; - int additional_flags = 0; - - hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags); - portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags); - - if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) { - hints->ai_socktype = SOCK_DGRAM; - } - hints->ai_flags |= additional_flags; - - if (NIL_P(timeout)) { - error = rb_getaddrinfo_a(hostp, portp, hints, &res, (struct timespec *)NULL); - } else { - struct timespec _timeout = rb_time_timespec_interval(timeout); - error = rb_getaddrinfo_a(hostp, portp, hints, &res, &_timeout); - } - - if (error) { - if (hostp && hostp[strlen(hostp)-1] == '\n') { - rb_raise(rb_eSocket, "newline at the end of hostname"); - } - rsock_raise_socket_error("getaddrinfo_a", error); - } - - return res; -} -#endif - int rsock_fd_family(int fd) { @@ -777,20 +551,6 @@ rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags) https://github.com/ruby/ruby/blob/trunk/ext/socket/raddrinfo.c#L551 return rsock_getaddrinfo(host, port, &hints, 1); } -#ifdef HAVE_GETADDRINFO_A -struct rb_addrinfo* -rsock_addrinfo_a(VALUE host, VALUE port, int family, int socktype, int flags, VALUE timeout) -{ - struct addrinfo hints; - - MEMZERO(&hints, struct addrinfo, 1); - hints.ai_family = family; - hints.ai_socktype = socktype; - hints.ai_flags = flags; - return rsock_getaddrinfo_a(host, port, &hints, 1, timeout); -} -#endif - VALUE rsock_ipaddr(s (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/