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
This commit is contained in:
Daniel Stenberg 2020-01-26 17:51:01 +01:00
parent 872ea75acf
commit 0b030a5b23
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
8 changed files with 27 additions and 25 deletions

View File

@ -669,7 +669,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
res->last_status = ARES_ENOTFOUND; res->last_status = ARES_ENOTFOUND;
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
if(family == PF_UNSPEC) { if(family == PF_UNSPEC) {
if(Curl_ipv6works()) { if(Curl_ipv6works(conn)) {
res->num_pending = 2; res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */ /* areschannel is already setup in the Curl_open() function */

View File

@ -743,7 +743,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
break; break;
} }
if((pf != PF_INET) && !Curl_ipv6works()) if((pf != PF_INET) && !Curl_ipv6works(conn))
/* The stack seems to be a non-IPv6 one */ /* The stack seems to be a non-IPv6 one */
pf = PF_INET; pf = PF_INET;
#endif /* CURLRES_IPV6 */ #endif /* CURLRES_IPV6 */

View File

@ -185,8 +185,6 @@ static CURLcode global_init(long flags, bool memoryfuncs)
goto fail; goto fail;
} }
(void)Curl_ipv6works();
#if defined(USE_SSH) #if defined(USE_SSH)
if(Curl_ssh_init()) { if(Curl_ssh_init()) {
goto fail; goto fail;

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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. * Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/ */
bool Curl_ipv6works(void); bool Curl_ipv6works(struct connectdata *conn);
#else #else
#define Curl_ipv6works() FALSE #define Curl_ipv6works(x) FALSE
#endif #endif
/* /*

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -62,13 +62,19 @@
/* /*
* Curl_ipv6works() returns TRUE if IPv6 seems to work. * 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 if(conn) {
during a program's lifetime so we only probe the first time and then we /* the nature of most system is that IPv6 status doesn't come and go
have the info kept for fast re-use */ during a program's lifetime so we only probe the first time and then we
static int ipv6_works = -1; have the info kept for fast re-use */
if(-1 == ipv6_works) { 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 */ /* probe to see if we have a working IPv6 stack */
curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
if(s == CURL_SOCKET_BAD) if(s == CURL_SOCKET_BAD)
@ -78,8 +84,8 @@ bool Curl_ipv6works(void)
ipv6_works = 1; ipv6_works = 1;
Curl_closesocket(NULL, s); 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) bool Curl_ipvalid(struct connectdata *conn)
{ {
if(conn->ip_version == CURL_IPRESOLVE_V6) if(conn->ip_version == CURL_IPRESOLVE_V6)
return Curl_ipv6works(); return Curl_ipv6works(conn);
return TRUE; return TRUE;
} }
@ -159,7 +165,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
break; break;
} }
if((pf != PF_INET) && !Curl_ipv6works()) if((pf != PF_INET) && !Curl_ipv6works(conn))
/* The stack seems to be a non-IPv6 one */ /* The stack seems to be a non-IPv6 one */
pf = PF_INET; pf = PF_INET;

View File

@ -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 */ /* -1 means it not set by user, use the default value */
multi->maxconnects = -1; multi->maxconnects = -1;
multi->max_concurrent_streams = 100; multi->max_concurrent_streams = 100;
multi->ipv6_works = Curl_ipv6works(NULL);
#ifdef ENABLE_WAKEUP #ifdef ENABLE_WAKEUP
if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) { if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {

View File

@ -119,11 +119,6 @@ struct Curl_multi {
same actual socket) */ same actual socket) */
struct curl_hash sockhash; struct curl_hash sockhash;
/* multiplexing wanted */
bool multiplexing;
bool recheckstate; /* see Curl_multi_connchanged */
/* Shared connection cache (bundles)*/ /* Shared connection cache (bundles)*/
struct conncache conn_cache; struct conncache conn_cache;
@ -141,13 +136,17 @@ struct Curl_multi {
void *timer_userp; void *timer_userp;
struct curltime timer_lastcall; /* the fixed time for the timeout for the struct curltime timer_lastcall; /* the fixed time for the timeout for the
previous callback */ previous callback */
bool in_callback; /* true while executing a callback */
unsigned int max_concurrent_streams; unsigned int max_concurrent_streams;
#ifdef ENABLE_WAKEUP #ifdef ENABLE_WAKEUP
curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup
0 is used for read, 1 is used for write */ 0 is used for read, 1 is used for write */
#endif #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 */ #endif /* HEADER_CURL_MULTIHANDLE_H */

View File

@ -36,8 +36,6 @@ nothing
# Verify data after the test has been "shot" # Verify data after the test has been "shot"
<verify> <verify>
<file name="log/memdump"> <file name="log/memdump">
FD hostip6.c: socket()
FD connect.c: sclose()
MEM lib558.c: malloc() MEM lib558.c: malloc()
MEM lib558.c: free() MEM lib558.c: free()
MEM escape.c: malloc() MEM escape.c: malloc()