From 0b030a5b232bd9fc4fed90f0d1aaac69c189aa22 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 26 Jan 2020 17:51:01 +0100 Subject: global_init: move the IPv6 works status bool to multi handle Previously it was stored in a global state which contributed to curl_global_init's thread unsafety. This boolean is now instead figured out in curl_multi_init() and stored in the multi handle. Less effective, but thread safe. Closes #4851 --- lib/asyn-ares.c | 2 +- lib/asyn-thread.c | 2 +- lib/easy.c | 2 -- lib/hostip.h | 6 +++--- lib/hostip6.c | 26 ++++++++++++++++---------- lib/multi.c | 1 + lib/multihandle.h | 11 +++++------ 7 files changed, 27 insertions(+), 23 deletions(-) (limited to 'lib') diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index ed52a740b..b76e66548 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -669,7 +669,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, res->last_status = ARES_ENOTFOUND; #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ if(family == PF_UNSPEC) { - if(Curl_ipv6works()) { + if(Curl_ipv6works(conn)) { res->num_pending = 2; /* areschannel is already setup in the Curl_open() function */ diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index d11573860..6a6dce107 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -743,7 +743,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, break; } - if((pf != PF_INET) && !Curl_ipv6works()) + if((pf != PF_INET) && !Curl_ipv6works(conn)) /* The stack seems to be a non-IPv6 one */ pf = PF_INET; #endif /* CURLRES_IPV6 */ diff --git a/lib/easy.c b/lib/easy.c index 0ad33c02b..98646c9c4 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -185,8 +185,6 @@ static CURLcode global_init(long flags, bool memoryfuncs) goto fail; } - (void)Curl_ipv6works(); - #if defined(USE_SSH) if(Curl_ssh_init()) { goto fail; diff --git a/lib/hostip.h b/lib/hostip.h index e0597ea96..a1c343ad7 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -96,9 +96,9 @@ int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, /* * Curl_ipv6works() returns TRUE if IPv6 seems to work. */ -bool Curl_ipv6works(void); +bool Curl_ipv6works(struct connectdata *conn); #else -#define Curl_ipv6works() FALSE +#define Curl_ipv6works(x) FALSE #endif /* diff --git a/lib/hostip6.c b/lib/hostip6.c index e0e0c58df..41ff98696 100644 --- a/lib/hostip6.c +++ b/lib/hostip6.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -62,13 +62,19 @@ /* * Curl_ipv6works() returns TRUE if IPv6 seems to work. */ -bool Curl_ipv6works(void) +bool Curl_ipv6works(struct connectdata *conn) { - /* the nature of most system is that IPv6 status doesn't come and go - during a program's lifetime so we only probe the first time and then we - have the info kept for fast re-use */ - static int ipv6_works = -1; - if(-1 == ipv6_works) { + if(conn) { + /* the nature of most system is that IPv6 status doesn't come and go + during a program's lifetime so we only probe the first time and then we + have the info kept for fast re-use */ + DEBUGASSERT(conn); + DEBUGASSERT(conn->data); + DEBUGASSERT(conn->data->multi); + return conn->data->multi->ipv6_works; + } + else { + int ipv6_works = -1; /* probe to see if we have a working IPv6 stack */ curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); if(s == CURL_SOCKET_BAD) @@ -78,8 +84,8 @@ bool Curl_ipv6works(void) ipv6_works = 1; Curl_closesocket(NULL, s); } + return (ipv6_works>0)?TRUE:FALSE; } - return (ipv6_works>0)?TRUE:FALSE; } /* @@ -89,7 +95,7 @@ bool Curl_ipv6works(void) bool Curl_ipvalid(struct connectdata *conn) { if(conn->ip_version == CURL_IPRESOLVE_V6) - return Curl_ipv6works(); + return Curl_ipv6works(conn); return TRUE; } @@ -159,7 +165,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, break; } - if((pf != PF_INET) && !Curl_ipv6works()) + if((pf != PF_INET) && !Curl_ipv6works(conn)) /* The stack seems to be a non-IPv6 one */ pf = PF_INET; diff --git a/lib/multi.c b/lib/multi.c index 1b79d42a4..b641074d4 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -370,6 +370,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ /* -1 means it not set by user, use the default value */ multi->maxconnects = -1; multi->max_concurrent_streams = 100; + multi->ipv6_works = Curl_ipv6works(NULL); #ifdef ENABLE_WAKEUP if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) { diff --git a/lib/multihandle.h b/lib/multihandle.h index b0cd0b821..91eca16c4 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -119,11 +119,6 @@ struct Curl_multi { same actual socket) */ struct curl_hash sockhash; - /* multiplexing wanted */ - bool multiplexing; - - bool recheckstate; /* see Curl_multi_connchanged */ - /* Shared connection cache (bundles)*/ struct conncache conn_cache; @@ -141,13 +136,17 @@ struct Curl_multi { void *timer_userp; struct curltime timer_lastcall; /* the fixed time for the timeout for the previous callback */ - bool in_callback; /* true while executing a callback */ unsigned int max_concurrent_streams; #ifdef ENABLE_WAKEUP curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup 0 is used for read, 1 is used for write */ #endif + /* multiplexing wanted */ + bool multiplexing; + bool recheckstate; /* see Curl_multi_connchanged */ + bool in_callback; /* true while executing a callback */ + bool ipv6_works; }; #endif /* HEADER_CURL_MULTIHANDLE_H */ -- cgit v1.2.3