share: concurrency handling, easy updates
No binary (build failed)
—
(log yok)
| @@ -630,15 +630,20 @@ if(DOS OR AMIGA) | |
| set(HAVE_TIME_T_UNSIGNED 1) | |
| endif() | |
| + | if(NOT WIN32) |
| + | find_package(Threads) |
| + | set(HAVE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT}) |
| + | set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT}) |
| + | list(APPEND CURL_NETWORK_AND_TIME_LIBS ${CMAKE_THREAD_LIBS_INIT}) |
| + | endif() |
| + | |
| if(ENABLE_THREADED_RESOLVER) | |
| - | if(WIN32) |
| - | set(USE_THREADS_WIN32 ON) |
| - | else() |
| - | find_package(Threads REQUIRED) |
| - | set(USE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT}) |
| - | set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT}) |
| - | list(APPEND CURL_NETWORK_AND_TIME_LIBS ${CMAKE_THREAD_LIBS_INIT}) |
| + | if(NOT WIN32 AND NOT HAVE_THREADS_POSIX) |
| + | message(FATAL_ERROR "Threaded resolver requires POSIX Threads.") |
| endif() | |
| + | set(USE_RESOLV_THREADED ON) |
| + | elseif(USE_ARES) |
| + | set(USE_RESOLV_ARES ON) |
| endif() | |
| # Check for all needed libraries | |
| @@ -1998,8 +2003,8 @@ curl_add_if("libz" HAVE_LIBZ) | |
| curl_add_if("brotli" HAVE_BROTLI) | |
| curl_add_if("gsasl" USE_GSASL) | |
| curl_add_if("zstd" HAVE_ZSTD) | |
| - | curl_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32) |
| - | curl_add_if("asyn-rr" USE_ARES AND ENABLE_THREADED_RESOLVER AND USE_HTTPSRR) |
| + | curl_add_if("AsynchDNS" USE_RESOLV_ARES OR USE_RESOLV_THREADED) |
| + | curl_add_if("asyn-rr" USE_ARES AND USE_RESOLV_THREADED AND USE_HTTPSRR) |
| curl_add_if("IDN" (HAVE_LIBIDN2 AND HAVE_IDN2_H) OR | |
| USE_WIN32_IDN OR | |
| USE_APPLE_IDN) | |
| @@ -2022,7 +2027,7 @@ curl_add_if("HTTPS-proxy" NOT CURL_DISABLE_PROXY AND _ssl_enabled AND (USE_OPE | |
| OR USE_SCHANNEL OR USE_RUSTLS OR USE_MBEDTLS OR | |
| (USE_WOLFSSL AND HAVE_WOLFSSL_BIO_NEW))) | |
| curl_add_if("Unicode" ENABLE_UNICODE) | |
| - | curl_add_if("threadsafe" HAVE_ATOMIC OR (USE_THREADS_POSIX AND HAVE_PTHREAD_H) OR WIN32) |
| + | curl_add_if("threadsafe" HAVE_ATOMIC OR (HAVE_THREADS_POSIX AND HAVE_PTHREAD_H) OR WIN32) |
| curl_add_if("Debug" ENABLE_DEBUG) | |
| curl_add_if("ECH" _ssl_enabled AND HAVE_ECH) | |
| curl_add_if("HTTPSRR" _ssl_enabled AND USE_HTTPSRR) | |
| @@ -4246,15 +4246,8 @@ if test "$ipv6" = "yes" && test "$curl_cv_apple" = "yes"; then | |
| CURL_DARWIN_SYSTEMCONFIGURATION | |
| fi | |
| - | dnl Windows threaded resolver check |
| - | if test "$want_threaded_resolver" = "yes" && test "$curl_cv_native_windows" = "yes"; then |
| - | USE_THREADS_WIN32=1 |
| - | AC_DEFINE(USE_THREADS_WIN32, 1, [if you want Win32 threaded DNS lookup]) |
| - | curl_res_msg="Win32 threaded" |
| - | fi |
| - | |
| dnl detect pthreads | |
| - | if test "$want_threaded_resolver" = "yes" && test "$USE_THREADS_WIN32" != "1"; then |
| + | if test "$curl_cv_native_windows" != "yes"; then |
| AC_CHECK_HEADER(pthread.h, | |
| [ AC_DEFINE(HAVE_PTHREAD_H, 1, [if you have <pthread.h>]) | |
| save_CFLAGS="$CFLAGS" | |
| @@ -4267,7 +4260,7 @@ if test "$want_threaded_resolver" = "yes" && test "$USE_THREADS_WIN32" != "1"; t | |
| LIBS= | |
| dnl Check for libc variants without a separate pthread lib like bionic | |
| - | AC_CHECK_FUNC(pthread_create, [USE_THREADS_POSIX=1] ) |
| + | AC_CHECK_FUNC(pthread_create, [HAVE_THREADS_POSIX=1] ) |
| LIBS="$save_LIBS" | |
| case $host in | |
| @@ -4279,7 +4272,7 @@ if test "$want_threaded_resolver" = "yes" && test "$USE_THREADS_WIN32" != "1"; t | |
| esac | |
| dnl if it was not found without lib, search for it in pthread lib | |
| - | if test "$USE_THREADS_POSIX" != "1"; then |
| + | if test "$HAVE_THREADS_POSIX" != "1"; then |
| # assign PTHREAD for pkg-config use | |
| PTHREAD=" -pthread" | |
| @@ -4302,20 +4295,32 @@ if test "$want_threaded_resolver" = "yes" && test "$USE_THREADS_WIN32" != "1"; t | |
| ;; | |
| esac | |
| AC_CHECK_LIB(pthread, pthread_create, | |
| - | [USE_THREADS_POSIX=1], |
| + | [HAVE_THREADS_POSIX=1], |
| [ CFLAGS="$save_CFLAGS"]) | |
| fi | |
| - | |
| - | if test "$USE_THREADS_POSIX" = "1"; then |
| - | AC_DEFINE(USE_THREADS_POSIX, 1, [if you want POSIX threaded DNS lookup]) |
| - | curl_res_msg="POSIX threaded" |
| - | fi |
| ]) | |
| + | if test "$HAVE_THREADS_POSIX" = "1"; then |
| + | AC_DEFINE(HAVE_THREADS_POSIX, 1, [if POSIX pthreads are supported]) |
| + | fi |
| fi | |
| - | dnl Did we find a threading option? |
| - | if test "$want_threaded_resolver" != "no" && test "$USE_THREADS_POSIX" != "1" && test "$USE_THREADS_WIN32" != "1"; then |
| - | AC_MSG_ERROR([Threaded resolver enabled but no thread library found]) |
| + | dnl threaded resolver check |
| + | if test "$want_threaded_resolver" = "yes"; then |
| + | if test "$curl_cv_native_windows" = "yes"; then |
| + | USE_RESOLV_THREADED=1 |
| + | AC_DEFINE(USE_RESOLV_THREADED, 1, [if you want threaded DNS lookup]) |
| + | curl_res_msg="Win32 threaded" |
| + | elif test "$HAVE_THREADS_POSIX" = "1"; then |
| + | USE_RESOLV_THREADED=1 |
| + | AC_DEFINE(USE_RESOLV_THREADED, 1, [if you want threaded DNS lookup]) |
| + | curl_res_msg="POSIX threaded" |
| + | else |
| + | AC_MSG_ERROR([Threaded resolver enabled but no thread library found]) |
| + | fi |
| + | elif test "$USE_ARES" = "1"; then |
| + | USE_RESOLV_ARES=1 |
| + | AC_DEFINE(USE_RESOLV_ARES, 1, [if you want c-ares for DNS lookup]) |
| + | curl_res_msg="c-ares" |
| fi | |
| AC_CHECK_HEADER(dirent.h, | |
| @@ -5157,7 +5162,7 @@ fi | |
| if test "$HAVE_ZSTD" = "1"; then | |
| SUPPORT_FEATURES="$SUPPORT_FEATURES zstd" | |
| fi | |
| - | if test "$USE_ARES" = "1" || test "$USE_THREADS_POSIX" = "1" || test "$USE_THREADS_WIN32" = "1"; then |
| + | if test "$USE_RESOLV_ARES" = "1" || test "$USE_RESOLV_THREADED" = "1"; then |
| SUPPORT_FEATURES="$SUPPORT_FEATURES AsynchDNS" | |
| fi | |
| if test "$USE_ARES" = "1" && test "$want_threaded_resolver" = "yes" && test "$want_httpsrr" != "no"; then | |
| @@ -5291,7 +5296,7 @@ fi | |
| if test "$tst_atomic" = "yes"; then | |
| SUPPORT_FEATURES="$SUPPORT_FEATURES threadsafe" | |
| - | elif test "$USE_THREADS_POSIX" = "1" && test "$ac_cv_header_pthread_h" = "yes"; then |
| + | elif test "$HAVE_THREADS_POSIX" = "1" && test "$ac_cv_header_pthread_h" = "yes"; then |
| SUPPORT_FEATURES="$SUPPORT_FEATURES threadsafe" | |
| elif test "$curl_cv_native_windows" = "yes"; then | |
| SUPPORT_FEATURES="$SUPPORT_FEATURES threadsafe" | |
| @@ -27,7 +27,8 @@ CURLSHcode curl_share_cleanup(CURLSH *share_handle); | |
| # DESCRIPTION | |
| This function deletes a shared object. The share handle cannot be used anymore | |
| - | when this function has been called. |
| + | when this function has been called. The share fails the call if it is |
| + | still being used in any easy handle. |
| Passing in a NULL pointer in *share_handle* makes this function return | |
| immediately with no action. | |
| @@ -35,6 +36,11 @@ immediately with no action. | |
| Any use of the **share_handle** after this function has been called and have | |
| returned, is illegal. | |
| + | For applications that use a share in several threads, it is critical that |
| + | the destruction of the share is only done when all other threads have stopped |
| + | using it. While libcurl tracks how many easy handles are using a share, |
| + | it can not observe how many pointers to the share the application has. |
| + | |
| # %PROTOCOLS% | |
| # EXAMPLE | |
| @@ -141,7 +141,7 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, uint16_t port) | |
| } | |
| } | |
| else { | |
| - | #ifdef CURLRES_THREADED |
| + | #ifdef USE_RESOLV_THREADED |
| /* gethostbyname() is not thread-safe, so we need to reopen bsdsocket | |
| * on the thread's context | |
| */ | |
| @@ -23,7 +23,7 @@ | |
| ***************************************************************************/ | |
| #include "curl_setup.h" | |
| - | #ifdef CURLRES_ARES |
| + | #ifdef USE_RESOLV_ARES |
| /*********************************************************************** | |
| * Only for ares-enabled builds and only for functions that fulfill | |
| @@ -966,4 +966,4 @@ CURLcode Curl_async_ares_set_dns_local_ip6(struct Curl_easy *data) | |
| #endif | |
| } | |
| - | #endif /* CURLRES_ARES */ |
| + | #endif /* USE_RESOLV_ARES */ |
| @@ -183,10 +183,10 @@ void Curl_async_shutdown(struct Curl_easy *data) | |
| { | |
| if(data->state.async) { | |
| CURL_TRC_DNS(data, "shutdown async"); | |
| - | #ifdef CURLRES_ARES |
| + | #ifdef USE_RESOLV_ARES |
| Curl_async_ares_shutdown(data, data->state.async); | |
| #endif | |
| - | #ifdef CURLRES_THREADED |
| + | #ifdef USE_RESOLV_THREADED |
| Curl_async_thrdd_shutdown(data, data->state.async); | |
| #endif | |
| #ifndef CURL_DISABLE_DOH | |
| @@ -199,10 +199,10 @@ void Curl_async_destroy(struct Curl_easy *data) | |
| { | |
| if(data->state.async) { | |
| CURL_TRC_DNS(data, "destroy async"); | |
| - | #ifdef CURLRES_ARES |
| + | #ifdef USE_RESOLV_ARES |
| Curl_async_ares_destroy(data, data->state.async); | |
| #endif | |
| - | #ifdef CURLRES_THREADED |
| + | #ifdef USE_RESOLV_THREADED |
| Curl_async_thrdd_destroy(data, data->state.async); | |
| #endif | |
| #ifndef CURL_DISABLE_DOH | |
| @@ -26,7 +26,7 @@ | |
| /*********************************************************************** | |
| * Only for threaded name resolves builds | |
| **********************************************************************/ | |
| - | #ifdef CURLRES_THREADED |
| + | #ifdef USE_RESOLV_THREADED |
| #include "socketpair.h" | |
| @@ -44,7 +44,7 @@ | |
| #include <inet.h> | |
| #endif | |
| - | #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) |
| + | #if defined(HAVE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) |
| #include <pthread.h> | |
| #endif | |
| @@ -739,4 +739,4 @@ CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, | |
| #endif /* !HAVE_GETADDRINFO */ | |
| - | #endif /* CURLRES_THREADED */ |
| + | #endif /* USE_RESOLV_THREADED */ |
| @@ -41,8 +41,8 @@ struct hostent; | |
| struct connectdata; | |
| struct easy_pollset; | |
| - | #if defined(CURLRES_ARES) && defined(CURLRES_THREADED) |
| - | #error cannot have both CURLRES_ARES and CURLRES_THREADED defined |
| + | #if defined(USE_RESOLV_ARES) && defined(USE_RESOLV_THREADED) |
| + | #error cannot have both USE_RESOLV_ARES and USE_RESOLV_THREADED defined |
| #endif | |
| /* | |
| @@ -134,7 +134,7 @@ CURLcode Curl_ares_pollset(struct Curl_easy *data, | |
| int Curl_ares_perform(ares_channel channel, timediff_t timeout_ms); | |
| #endif | |
| - | #ifdef CURLRES_ARES |
| + | #ifdef USE_RESOLV_ARES |
| /* async resolving implementation using c-ares alone */ | |
| struct async_ares_ctx { | |
| ares_channel channel; | |
| @@ -168,9 +168,9 @@ CURLcode Curl_async_ares_set_dns_local_ip4(struct Curl_easy *data); | |
| /* Set the local ipv6 address to use by ares, from `data` settings. */ | |
| CURLcode Curl_async_ares_set_dns_local_ip6(struct Curl_easy *data); | |
| - | #endif /* CURLRES_ARES */ |
| + | #endif /* USE_RESOLV_ARES */ |
| - | #ifdef CURLRES_THREADED |
| + | #ifdef USE_RESOLV_THREADED |
| /* async resolving implementation using POSIX threads */ | |
| #include "curl_threads.h" | |
| @@ -219,7 +219,7 @@ void Curl_async_thrdd_shutdown(struct Curl_easy *data, | |
| void Curl_async_thrdd_destroy(struct Curl_easy *data, | |
| struct Curl_resolv_async *async); | |
| - | #endif /* CURLRES_THREADED */ |
| + | #endif /* USE_RESOLV_THREADED */ |
| #ifndef CURL_DISABLE_DOH | |
| struct doh_probes; | |
| @@ -242,9 +242,9 @@ struct doh_probes; | |
| #ifdef USE_CURL_ASYNC | |
| struct Curl_resolv_async { | |
| - | #ifdef CURLRES_ARES |
| + | #ifdef USE_RESOLV_ARES |
| struct async_ares_ctx ares; | |
| - | #elif defined(CURLRES_THREADED) |
| + | #elif defined(USE_RESOLV_THREADED) |
| struct async_thrdd_ctx thrdd; | |
| #endif | |
| #ifndef CURL_DISABLE_DOH | |
| @@ -262,15 +262,16 @@ | |
| /* ---------------------------------------------------------------- */ | |
| /* | |
| - | * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS. |
| + | * Undefine both USE_ARES and USE_RESOLV_THREADED for synchronous DNS. |
| */ | |
| /* Default define to enable threaded asynchronous DNS lookups. */ | |
| - | #if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && !defined(USE_THREADS_WIN32) |
| - | # define USE_THREADS_WIN32 1 |
| + | #if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && \ |
| + | !defined(USE_RESOLV_THREADED) |
| + | # define USE_RESOLV_THREADED 1 |
| #endif | |
| - | #if defined(USE_ARES) && defined(USE_THREADS_WIN32) |
| + | #if defined(USE_ARES) && defined(USE_RESOLV_THREADED) |
| # error "Only one DNS lookup specialty may be defined at most" | |
| #endif | |
| @@ -643,14 +643,17 @@ ${SIZEOF_TIME_T_CODE} | |
| /* Define to 1 if you have the ANSI C header files. */ | |
| #cmakedefine STDC_HEADERS 1 | |
| + | /* Define if you have POSIX pthreads */ |
| + | #cmakedefine HAVE_THREADS_POSIX 1 |
| + | |
| /* Define if you want to enable c-ares support */ | |
| #cmakedefine USE_ARES 1 | |
| - | /* Define if you want to enable POSIX threaded DNS lookup */ |
| - | #cmakedefine USE_THREADS_POSIX 1 |
| + | /* Define if you want to enable c-ares DNS lookup */ |
| + | #cmakedefine USE_RESOLV_ARES 1 |
| - | /* Define if you want to enable Win32 threaded DNS lookup */ |
| - | #cmakedefine USE_THREADS_WIN32 1 |
| + | /* Define if you want to enable threaded DNS lookup */ |
| + | #cmakedefine USE_RESOLV_THREADED 1 |
| /* if GnuTLS is enabled */ | |
| #cmakedefine USE_GNUTLS 1 | |
| @@ -220,7 +220,7 @@ | |
| /* ================================================================ */ | |
| /* Give calloc a chance to be dragging in early, so we do not redefine */ | |
| - | #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) |
| + | #if defined(HAVE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) |
| # include <pthread.h> | |
| #endif | |
| @@ -442,7 +442,7 @@ | |
| # if !(defined(__NEWLIB__) || \ | |
| (defined(__CLIB2__) && defined(__THREAD_SAFE))) | |
| /* disable threaded resolver with clib2 - requires newlib or clib-ts */ | |
| - | # undef USE_THREADS_POSIX |
| + | # undef USE_RESOLV_THREADED |
| # endif | |
| # endif | |
| # include <exec/types.h> | |
| @@ -685,6 +685,16 @@ | |
| #endif /* _WIN32 */ | |
| + | /* We want to use mutex when available. */ |
| + | #if defined(HAVE_THREADS_POSIX) || defined(_WIN32) |
| + | #define USE_MUTEX |
| + | #endif |
| + | |
| + | /* threaded resolver is the only feature requiring threads. */ |
| + | #ifdef USE_RESOLV_THREADED |
| + | #define USE_THREADS |
| + | #endif |
| + | |
| /* ---------------------------------------------------------------- */ | |
| /* resolver specialty compile-time defines */ | |
| /* CURLRES_* defines to use in the host*.c sources */ | |
| @@ -702,12 +712,10 @@ | |
| # define CURLRES_IPV4 | |
| #endif | |
| - | #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) |
| + | #ifdef USE_RESOLV_THREADED |
| # define CURLRES_ASYNCH | |
| - | # define CURLRES_THREADED |
| - | #elif defined(USE_ARES) |
| + | #elif defined(USE_RESOLV_ARES) |
| # define CURLRES_ASYNCH | |
| - | # define CURLRES_ARES |
| /* now undef the stock libc functions to avoid them being used */ | |
| # undef HAVE_GETADDRINFO | |
| # undef HAVE_FREEADDRINFO | |
| @@ -24,22 +24,61 @@ | |
| #include "curl_setup.h" | |
| #include "urldata.h" | |
| + | #include "multiif.h" |
| + | #include "curl_threads.h" |
| #include "curl_share.h" | |
| #include "vtls/vtls.h" | |
| #include "vtls/vtls_scache.h" | |
| #include "hsts.h" | |
| #include "url.h" | |
| + | static void share_destroy(struct Curl_share *share) |
| + | { |
| + | if(share->specifier & (1 << CURL_LOCK_DATA_CONNECT)) { |
| + | Curl_cpool_destroy(&share->cpool); |
| + | } |
| + | |
| + | Curl_dnscache_destroy(&share->dnscache); |
| + | |
| + | #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) |
| + | Curl_cookie_cleanup(share->cookies); |
| + | #endif |
| + | |
| + | #ifndef CURL_DISABLE_HSTS |
| + | Curl_hsts_cleanup(&share->hsts); |
| + | #endif |
| + | |
| + | #ifdef USE_SSL |
| + | if(share->ssl_scache) { |
| + | Curl_ssl_scache_destroy(share->ssl_scache); |
| + | share->ssl_scache = NULL; |
| + | } |
| + | #endif |
| + | |
| + | Curl_psl_destroy(&share->psl); |
| + | Curl_close(&share->admin); |
| + | |
| + | #ifdef USE_MUTEX |
| + | Curl_mutex_destroy(&share->lock); |
| + | #endif |
| + | share->magic = 0; |
| + | curlx_free(share); |
| + | } |
| + | |
| CURLSH *curl_share_init(void) | |
| { | |
| struct Curl_share *share = curlx_calloc(1, sizeof(struct Curl_share)); | |
| if(share) { | |
| share->magic = CURL_GOOD_SHARE; | |
| share->specifier |= (1 << CURL_LOCK_DATA_SHARE); | |
| + | #ifdef USE_MUTEX |
| + | Curl_mutex_init(&share->lock); |
| + | #endif |
| + | share->ref_count = 1; |
| Curl_dnscache_init(&share->dnscache, 23); | |
| share->admin = curl_easy_init(); | |
| if(!share->admin) { | |
| - | curlx_free(share); |
| + | share_destroy(share); |
| return NULL; | |
| } | |
| /* admin handles have mid 0 */ | |
| @@ -50,10 +89,104 @@ CURLSH *curl_share_init(void) | |
| share->admin->set.verbose = TRUE; | |
| #endif | |
| } | |
| - | |
| return share; | |
| } | |
| + | static uint32_t share_ref_inc(struct Curl_share *share) |
| + | { |
| + | uint32_t n; |
| + | #ifdef USE_MUTEX |
| + | Curl_mutex_acquire(&share->lock); |
| + | n = ++(share->ref_count); |
| + | share->has_been_shared = TRUE; |
| + | Curl_mutex_release(&share->lock); |
| + | #else |
| + | n = ++(share->ref_count); |
| + | share->has_been_shared = TRUE; |
| + | #endif |
| + | return n; |
| + | } |
| + | |
| + | static uint32_t share_ref_dec(struct Curl_share *share) |
| + | { |
| + | uint32_t n; |
| + | #ifdef USE_MUTEX |
| + | Curl_mutex_acquire(&share->lock); |
| + | DEBUGASSERT(share->ref_count); |
| + | n = --(share->ref_count); |
| + | Curl_mutex_release(&share->lock); |
| + | #else |
| + | n = --(share->ref_count); |
| + | #endif |
| + | return n; |
| + | } |
| + | |
| + | static bool share_has_been_shared(struct Curl_share *share) |
| + | { |
| + | bool was_shared; |
| + | #ifdef USE_MUTEX |
| + | Curl_mutex_acquire(&share->lock); |
| + | was_shared = share->has_been_shared; |
| + | Curl_mutex_release(&share->lock); |
| + | #else |
| + | was_shared = share->has_been_shared; |
| + | #endif |
| + | return was_shared; |
| + | } |
| + | |
| + | static bool share_lock_acquire(struct Curl_share *share, |
| + | struct Curl_easy *data) |
| + | { |
| + | if(share->lockfunc && share->unlockfunc && |
| + | (data || share_has_been_shared(share))) { |
| + | share->lockfunc(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, |
| + | share->clientdata); |
| + | return TRUE; |
| + | } |
| + | return FALSE; |
| + | } |
| + | |
| + | static void share_lock_release(struct Curl_share *share, |
| + | struct Curl_easy *data, |
| + | bool locked) |
| + | { |
| + | if(locked) { |
| + | DEBUGASSERT(share->unlockfunc); |
| + | if(share->unlockfunc) |
| + | share->unlockfunc(data, CURL_LOCK_DATA_SHARE, share->clientdata); |
| + | } |
| + | } |
| + | |
| + | static bool share_in_use(struct Curl_share *share) |
| + | { |
| + | bool in_use; |
| + | #ifdef USE_MUTEX |
| + | Curl_mutex_acquire(&share->lock); |
| + | in_use = (share->ref_count > 1); |
| + | Curl_mutex_release(&share->lock); |
| + | #else |
| + | bool locked = share_lock_acquire(share, NULL); |
| + | in_use = (share->ref_count > 1); |
| + | share_lock_release(share, NULL, locked); |
| + | #endif |
| + | return in_use; |
| + | } |
| + | |
| + | static void share_unlink(struct Curl_share **pshare, |
| + | struct Curl_easy *data, |
| + | bool locked) |
| + | { |
| + | struct Curl_share *share = *pshare; |
| + | uint32_t n; |
| + | |
| + | *pshare = NULL; |
| + | n = share_ref_dec(share); |
| + | if(locked) |
| + | share_lock_release(share, data, locked); |
| + | if(!n) /* last reference gone */ |
| + | share_destroy(share); |
| + | } |
| + | |
| #undef curl_share_setopt | |
| CURLSHcode curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) | |
| { | |
| @@ -68,10 +201,11 @@ CURLSHcode curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) | |
| if(!GOOD_SHARE_HANDLE(share)) | |
| return CURLSHE_INVALID; | |
| - | if(share->dirty) |
| + | if(share_in_use(share)) { |
| /* do not allow setting options while one or more handles are already | |
| using this share */ | |
| return CURLSHE_IN_USE; | |
| + | } |
| va_start(param, option); | |
| @@ -221,48 +355,15 @@ CURLSHcode curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) | |
| CURLSHcode curl_share_cleanup(CURLSH *sh) | |
| { | |
| struct Curl_share *share = sh; | |
| + | bool locked; |
| if(!GOOD_SHARE_HANDLE(share)) | |
| return CURLSHE_INVALID; | |
| - | if(share->lockfunc) |
| - | share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, |
| - | share->clientdata); |
| - | |
| - | if(share->dirty) { |
| - | if(share->unlockfunc) |
| - | share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); |
| + | if(share_in_use(share)) |
| return CURLSHE_IN_USE; | |
| - | } |
| - | |
| - | if(share->specifier & (1 << CURL_LOCK_DATA_CONNECT)) { |
| - | Curl_cpool_destroy(&share->cpool); |
| - | } |
| - | |
| - | Curl_dnscache_destroy(&share->dnscache); |
| - | |
| - | #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) |
| - | Curl_cookie_cleanup(share->cookies); |
| - | #endif |
| - | |
| - | #ifndef CURL_DISABLE_HSTS |
| - | Curl_hsts_cleanup(&share->hsts); |
| - | #endif |
| - | |
| - | #ifdef USE_SSL |
| - | if(share->ssl_scache) { |
| - | Curl_ssl_scache_destroy(share->ssl_scache); |
| - | share->ssl_scache = NULL; |
| - | } |
| - | #endif |
| - | |
| - | Curl_psl_destroy(&share->psl); |
| - | Curl_close(&share->admin); |
| - | |
| - | if(share->unlockfunc) |
| - | share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); |
| - | share->magic = 0; |
| - | curlx_free(share); |
| + | locked = share_lock_acquire(share, NULL); |
| + | share_unlink(&share, NULL, locked); |
| return CURLSHE_OK; | |
| } | |
| @@ -297,3 +398,78 @@ CURLSHcode Curl_share_unlock(struct Curl_easy *data, curl_lock_data type) | |
| return CURLSHE_OK; | |
| } | |
| + | |
| + | CURLcode Curl_share_easy_unlink(struct Curl_easy *data) |
| + | { |
| + | struct Curl_share *share = data->share; |
| + | |
| + | if(share) { |
| + | bool locked = share_lock_acquire(share, data); |
| + | |
| + | /* If data has a connection from this share, detach it. */ |
| + | if(data->conn && (share->specifier & (1 << CURL_LOCK_DATA_CONNECT))) |
| + | Curl_detach_connection(data); |
| + | |
| + | #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) |
| + | if(share->cookies == data->cookies) |
| + | data->cookies = NULL; |
| + | #endif |
| + | |
| + | #ifndef CURL_DISABLE_HSTS |
| + | if(share->hsts == data->hsts) |
| + | data->hsts = NULL; |
| + | #endif |
| + | #ifdef USE_LIBPSL |
| + | if(&share->psl == data->psl) |
| + | data->psl = data->multi ? &data->multi->psl : NULL; |
| + | #endif |
| + | if(share->specifier & (1 << CURL_LOCK_DATA_DNS)) { |
| + | Curl_dns_entry_unlink(data, &data->state.dns[0]); |
| + | Curl_dns_entry_unlink(data, &data->state.dns[1]); |
| + | } |
| + | |
| + | share_unlink(&data->share, data, locked); |
| + | } |
| + | return CURLE_OK; |
| + | } |
| + | |
| + | CURLcode Curl_share_easy_link(struct Curl_easy *data, |
| + | struct Curl_share *share) |
| + | { |
| + | if(data->share) { |
| + | DEBUGASSERT(0); |
| + | return CURLE_FAILED_INIT; |
| + | } |
| + | |
| + | if(share) { |
| + | bool locked = share_lock_acquire(share, data); |
| + | |
| + | share_ref_inc(share); |
| + | data->share = share; |
| + | |
| + | #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) |
| + | if(share->cookies) { |
| + | /* use shared cookie list, first free own one if any */ |
| + | Curl_cookie_cleanup(data->cookies); |
| + | /* enable cookies since we now use a share that uses cookies! */ |
| + | data->cookies = share->cookies; |
| + | } |
| + | #endif /* CURL_DISABLE_HTTP */ |
| + | #ifndef CURL_DISABLE_HSTS |
| + | if(share->hsts) { |
| + | /* first free the private one if any */ |
| + | Curl_hsts_cleanup(&data->hsts); |
| + | data->hsts = share->hsts; |
| + | } |
| + | #endif |
| + | #ifdef USE_LIBPSL |
| + | if(share->specifier & (1 << CURL_LOCK_DATA_PSL)) |
| + | data->psl = &share->psl; |
| + | #endif |
| + | |
| + | /* check for host cache not needed, |
| + | * it will be done by curl_easy_perform */ |
| + | share_lock_release(share, data, locked); |
| + | } |
| + | return CURLE_OK; |
| + | } |
| @@ -25,6 +25,7 @@ | |
| ***************************************************************************/ | |
| #include "curl_setup.h" | |
| + | #include "curl_threads.h" |
| #include "cookie.h" | |
| #include "psl.h" | |
| #include "urldata.h" | |
| @@ -43,12 +44,22 @@ struct Curl_ssl_scache; | |
| struct Curl_share { | |
| unsigned int magic; /* CURL_GOOD_SHARE */ | |
| unsigned int specifier; | |
| - | volatile unsigned int dirty; |
| + | uint32_t ref_count; |
| + | #ifdef USE_MUTEX |
| + | /* do `ref_count` and `has_been_shared` checks using this mutex. */ |
| + | curl_mutex_t lock; |
| + | int has_been_shared; |
| + | #else |
| + | /* this only ever goes from FALSE -> TRUE once. We need to check |
| + | * this without being able to use the `lockfunc`. */ |
| + | volatile int has_been_shared; |
| + | #endif |
| curl_lock_function lockfunc; | |
| curl_unlock_function unlockfunc; | |
| void *clientdata; | |
| struct Curl_easy *admin; | |
| + | |
| struct cpool cpool; | |
| struct Curl_dnscache dnscache; /* DNS cache */ | |
| #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) | |
| @@ -74,4 +85,8 @@ CURLSHcode Curl_share_unlock(struct Curl_easy *data, curl_lock_data type); | |
| ((data)->share->specifier & \ | |
| (1 << CURL_LOCK_DATA_SSL_SESSION))) | |
| + | CURLcode Curl_share_easy_unlink(struct Curl_easy *data); |
| + | CURLcode Curl_share_easy_link(struct Curl_easy *data, |
| + | struct Curl_share *share); |
| + | |
| #endif /* HEADER_CURL_SHARE_H */ | |
| @@ -22,14 +22,11 @@ | |
| * | |
| ***************************************************************************/ | |
| #include "curl_setup.h" | |
| - | |
| - | #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) |
| - | #include <pthread.h> |
| - | #endif |
| - | |
| #include "curl_threads.h" | |
| - | #ifdef USE_THREADS_POSIX |
| + | #ifdef USE_THREADS |
| + | |
| + | #ifdef HAVE_THREADS_POSIX |
| struct Curl_actual_call { | |
| unsigned int (*func)(void *); | |
| @@ -97,7 +94,7 @@ int Curl_thread_join(curl_thread_t *hnd) | |
| return ret; | |
| } | |
| - | #elif defined(USE_THREADS_WIN32) |
| + | #elif defined(_WIN32) |
| curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T | |
| (CURL_STDCALL *func) (void *), void *arg) | |
| @@ -131,4 +128,7 @@ int Curl_thread_join(curl_thread_t *hnd) | |
| return ret; | |
| } | |
| - | #endif /* USE_THREADS_* */ |
| + | #else |
| + | #error neither HAVE_THREADS_POSIX nor _WIN32 defined |
| + | #endif |
| + | #endif /* USE_THREADS */ |
| @@ -25,7 +25,11 @@ | |
| ***************************************************************************/ | |
| #include "curl_setup.h" | |
| - | #ifdef USE_THREADS_POSIX |
| + | #ifdef USE_MUTEX |
| + | #ifdef HAVE_THREADS_POSIX |
| + | #ifdef HAVE_PTHREAD_H |
| + | #include <pthread.h> |
| + | #endif |
| # define CURL_THREAD_RETURN_T unsigned int | |
| # define CURL_STDCALL | |
| # define curl_mutex_t pthread_mutex_t | |
| @@ -35,7 +39,7 @@ | |
| # define Curl_mutex_acquire(m) pthread_mutex_lock(m) | |
| # define Curl_mutex_release(m) pthread_mutex_unlock(m) | |
| # define Curl_mutex_destroy(m) pthread_mutex_destroy(m) | |
| - | #elif defined(USE_THREADS_WIN32) |
| + | #elif defined(_WIN32) |
| # define CURL_THREAD_RETURN_T DWORD | |
| # define CURL_STDCALL WINAPI | |
| # define curl_mutex_t CRITICAL_SECTION | |
| @@ -45,9 +49,12 @@ | |
| # define Curl_mutex_acquire(m) EnterCriticalSection(m) | |
| # define Curl_mutex_release(m) LeaveCriticalSection(m) | |
| # define Curl_mutex_destroy(m) DeleteCriticalSection(m) | |
| + | #else |
| + | #error neither HAVE_THREADS_POSIX nor _WIN32 defined |
| #endif | |
| + | #endif /* USE_MUTEX */ |
| - | #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) |
| + | #ifdef USE_THREADS |
| curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T | |
| (CURL_STDCALL *func) (void *), void *arg); | |
| @@ -56,6 +63,6 @@ void Curl_thread_destroy(curl_thread_t *hnd); | |
| int Curl_thread_join(curl_thread_t *hnd); | |
| - | #endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ |
| + | #endif /* USE_THREADS */ |
| #endif /* HEADER_CURL_THREADS_H */ | |
| @@ -84,7 +84,7 @@ static CURL_INLINE void curl_simple_lock_unlock(curl_simple_lock *lock) | |
| atomic_store_explicit(lock, false, memory_order_release); | |
| } | |
| - | #elif defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) |
| + | #elif defined(HAVE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) |
| #include <pthread.h> | |
| @@ -86,10 +86,10 @@ | |
| * take that into account. Hosts that are not IPv6-enabled have CURLRES_IPV4 | |
| * defined. | |
| * | |
| - | * CURLRES_ARES - is defined if libcurl is built to use c-ares for |
| + | * USE_RESOLV_ARES - is defined if libcurl is built to use c-ares for |
| * asynchronous name resolves. This can be Windows or *nix. | |
| * | |
| - | * CURLRES_THREADED - is defined if libcurl is built to run under (native) |
| + | * USE_RESOLV_THREADED - is defined if libcurl is built to run under (native) |
| * Windows, and then the name resolve will be done in a new thread, and the | |
| * supported API will be the same as for ares-builds. | |
| * | |
| @@ -85,7 +85,8 @@ struct Curl_addrinfo *Curl_sync_getaddrinfo(struct Curl_easy *data, | |
| #endif /* CURLRES_SYNCH */ | |
| #endif /* CURLRES_IPV4 */ | |
| - | #if defined(CURLRES_IPV4) && !defined(CURLRES_ARES) && !defined(CURLRES_AMIGA) |
| + | #if defined(CURLRES_IPV4) && !defined(USE_RESOLV_ARES) && \ |
| + | !defined(CURLRES_AMIGA) |
| /* | |
| * Curl_ipv4_resolve_r() - ipv4 thread-safe resolver function. | |
| @@ -277,4 +278,4 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, | |
| return ai; | |
| } | |
| - | #endif /* CURLRES_IPV4 && !CURLRES_ARES && !CURLRES_AMIGA */ |
| + | #endif /* CURLRES_IPV4 && !USE_RESOLV_ARES && !CURLRES_AMIGA */ |
| @@ -65,14 +65,14 @@ static struct backtrace_state *btstate; | |
| static char membuf[10000]; | |
| static size_t memwidx = 0; /* write index */ | |
| - | #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) |
| + | #ifdef USE_MUTEX |
| static bool dbg_mutex_init = 0; | |
| static curl_mutex_t dbg_mutex; | |
| #endif | |
| static bool curl_dbg_lock(void) | |
| { | |
| - | #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) |
| + | #ifdef USE_MUTEX |
| if(dbg_mutex_init) { | |
| Curl_mutex_acquire(&dbg_mutex); | |
| return TRUE; | |
| @@ -83,7 +83,7 @@ static bool curl_dbg_lock(void) | |
| static void curl_dbg_unlock(bool was_locked) | |
| { | |
| - | #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) |
| + | #ifdef USE_MUTEX |
| if(was_locked) | |
| Curl_mutex_release(&dbg_mutex); | |
| #else | |
| @@ -108,7 +108,7 @@ static void curl_dbg_cleanup(void) | |
| fclose(curl_dbg_logfile); | |
| } | |
| curl_dbg_logfile = NULL; | |
| - | #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) |
| + | #ifdef USE_MUTEX |
| if(dbg_mutex_init) { | |
| Curl_mutex_destroy(&dbg_mutex); | |
| dbg_mutex_init = FALSE; | |
| @@ -157,7 +157,7 @@ void curl_dbg_memdebug(const char *logname) | |
| setbuf(curl_dbg_logfile, (char *)NULL); | |
| #endif | |
| } | |
| - | #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) |
| + | #ifdef USE_MUTEX |
| if(!dbg_mutex_init) { | |
| dbg_mutex_init = TRUE; | |
| Curl_mutex_init(&dbg_mutex); | |
| @@ -1490,67 +1490,17 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, | |
| case CURLOPT_SHARE: { | |
| struct Curl_share *set = va_arg(param, struct Curl_share *); | |
| - | /* disconnect from old share, if any */ |
| - | if(data->share) { |
| - | Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); |
| - | |
| - | #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) |
| - | if(data->share->cookies == data->cookies) |
| - | data->cookies = NULL; |
| - | #endif |
| - | |
| - | #ifndef CURL_DISABLE_HSTS |
| - | if(data->share->hsts == data->hsts) |
| - | data->hsts = NULL; |
| - | #endif |
| - | #ifdef USE_LIBPSL |
| - | if(data->psl == &data->share->psl) |
| - | data->psl = data->multi ? &data->multi->psl : NULL; |
| - | #endif |
| - | if(data->share->specifier & (1 << CURL_LOCK_DATA_DNS)) { |
| - | Curl_dns_entry_unlink(data, &data->state.dns[0]); |
| - | Curl_dns_entry_unlink(data, &data->state.dns[1]); |
| - | } |
| - | |
| - | data->share->dirty--; |
| - | |
| - | Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); |
| - | data->share = NULL; |
| - | } |
| - | |
| - | if(GOOD_SHARE_HANDLE(set)) |
| - | /* use new share if it set */ |
| - | data->share = set; |
| - | if(data->share) { |
| - | |
| - | Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); |
| - | |
| - | data->share->dirty++; |
| - | |
| - | #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) |
| - | if(data->share->cookies) { |
| - | /* use shared cookie list, first free own one if any */ |
| - | Curl_cookie_cleanup(data->cookies); |
| - | /* enable cookies since we now use a share that uses cookies! */ |
| - | data->cookies = data->share->cookies; |
| - | } |
| - | #endif /* CURL_DISABLE_HTTP */ |
| - | #ifndef CURL_DISABLE_HSTS |
| - | if(data->share->hsts) { |
| - | /* first free the private one if any */ |
| - | Curl_hsts_cleanup(&data->hsts); |
| - | data->hsts = data->share->hsts; |
| - | } |
| - | #endif |
| - | #ifdef USE_LIBPSL |
| - | if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL)) |
| - | data->psl = &data->share->psl; |
| - | #endif |
| + | /* disconnect from old share, if any and possible */ |
| + | result = Curl_share_easy_unlink(data); |
| + | if(result) |
| + | return result; |
| - | Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); |
| + | /* use new share if it set */ |
| + | if(GOOD_SHARE_HANDLE(set)) { |
| + | result = Curl_share_easy_link(data, set); |
| + | if(result) |
| + | return result; |
| } | |
| - | /* check for host cache not needed, |
| - | * it will be done by curl_easy_perform */ |
| break; | |
| } | |
| @@ -2434,7 +2384,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, | |
| break; | |
| #endif | |
| #endif | |
| - | #ifdef CURLRES_ARES |
| + | #ifdef USE_RESOLV_ARES |
| case CURLOPT_DNS_SERVERS: | |
| result = Curl_setstropt(&s->str[STRING_DNS_SERVERS], ptr); | |
| if(result) | |
| @@ -287,11 +287,8 @@ CURLcode Curl_close(struct Curl_easy **datap) | |
| data_priority_cleanup(data); | |
| /* No longer a dirty share, if it exists */ | |
| - | if(data->share) { |
| - | Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); |
| - | data->share->dirty--; |
| - | Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); |
| - | } |
| + | if(Curl_share_easy_unlink(data)) |
| + | DEBUGASSERT(0); |
| Curl_hash_destroy(&data->meta_hash); | |
| #ifndef CURL_DISABLE_PROXY | |
| @@ -451,7 +451,7 @@ static const struct feat features_table[] = { | |
| #ifndef CURL_DISABLE_ALTSVC | |
| FEATURE("alt-svc", NULL, CURL_VERSION_ALTSVC), | |
| #endif | |
| - | #if defined(USE_ARES) && defined(CURLRES_THREADED) && defined(USE_HTTPSRR) |
| + | #if defined(USE_ARES) && defined(USE_RESOLV_THREADED) && defined(USE_HTTPSRR) |
| FEATURE("asyn-rr", NULL, 0), | |
| #endif | |
| #ifdef CURLRES_ASYNCH | |
| @@ -327,8 +327,8 @@ $write cvh "#endif" | |
| $write cvh "#ifdef USE_OPENLDAP" | |
| $write cvh "#undef USE_OPENLDAP" | |
| $write cvh "#endif" | |
| - | $write cvh "#ifdef USE_THREADS_POSIX" |
| - | $write cvh "#undef USE_THREADS_POSIX" |
| + | $write cvh "#ifdef USE_RESOLV_THREADED" |
| + | $write cvh "#undef USE_RESOLV_THREADED" |
| $write cvh "#endif" | |
| $write cvh "#ifdef USE_TLS_SRP" | |
| $write cvh "#undef USE_TLS_SRP" | |
| @@ -34,7 +34,7 @@ | |
| #include "multihandle.h" /* for ENABLE_WAKEUP */ | |
| #include "tool_xattr.h" /* for USE_XATTR */ | |
| #include "curl_sha512_256.h" /* for CURL_HAVE_SHA512_256 */ | |
| - | #include "asyn.h" /* for CURLRES_ARES */ |
| + | #include "asyn.h" /* for USE_RESOLV_ARES */ |
| #include "fake_addrinfo.h" /* for USE_FAKE_GETADDRINFO */ | |
| #include <stdio.h> | |
| @@ -235,7 +235,7 @@ static const char *disabled[] = { | |
| , | |
| "override-dns: " | |
| #if defined(CURL_MEMDEBUG) && \ | |
| - | (defined(CURLRES_ARES) || defined(USE_FAKE_GETADDRINFO)) |
| + | (defined(USE_RESOLV_ARES) || defined(USE_FAKE_GETADDRINFO)) |
| "ON" | |
| #else | |
| "OFF" | |
| @@ -227,17 +227,15 @@ loaded cookies: | |
| .host.foo.com TRUE / FALSE %days[400] injected yes | |
| ----------------- | |
| try SHARE_CLEANUP... | |
| - | lock: share [Pigs in space]: 98 |
| - | unlock: share [Pigs in space]: 99 |
| SHARE_CLEANUP failed, correct | |
| CLEANUP | |
| - | lock: cookie [Pigs in space]: 100 |
| - | unlock: cookie [Pigs in space]: 101 |
| + | lock: cookie [Pigs in space]: 98 |
| + | unlock: cookie [Pigs in space]: 99 |
| + | lock: share [Pigs in space]: 100 |
| + | unlock: share [Pigs in space]: 101 |
| + | SHARE_CLEANUP |
| lock: share [Pigs in space]: 102 | |
| unlock: share [Pigs in space]: 103 | |
| - | SHARE_CLEANUP |
| - | lock: share [Pigs in space]: 104 |
| - | unlock: share [Pigs in space]: 105 |
| GLOBAL_CLEANUP | |
| </stdout> | |
| <file name="%LOGDIR/jar%TESTNUMBER" mode="text"> | |
| @@ -23,10 +23,6 @@ | |
| ***************************************************************************/ | |
| #include "first.h" | |
| - | #ifdef USE_THREADS_POSIX |
| - | #include <pthread.h> |
| - | #endif |
| - | |
| #include "curl_threads.h" | |
| #define THREAD_SIZE 16 | |
| @@ -66,7 +62,7 @@ static size_t write_memory_callback(char *contents, size_t size, | |
| return realsize; | |
| } | |
| - | #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) |
| + | #ifdef USE_THREADS |
| static CURL_THREAD_RETURN_T CURL_STDCALL test_thread(void *ptr) | |
| #else | |
| static unsigned int test_thread(void *ptr) | |
| @@ -111,7 +107,7 @@ test_cleanup: | |
| return 0; | |
| } | |
| - | #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) |
| + | #ifdef USE_THREADS |
| static void t3207_test_lock(CURL *curl, curl_lock_data data, | |
| curl_lock_access laccess, void *useptr) | |