diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-10-02 11:52:55 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-10-02 12:46:18 +0300 |
commit | 2084bac66bb1c8d3013d8ef6c61867726c4188e2 (patch) | |
tree | 156097eba7a9e2c4f2f0deb087446006f1bd247f | |
parent | a830a77de6483eb53f266f2161931315324cacca (diff) | |
download | ydb-2084bac66bb1c8d3013d8ef6c61867726c4188e2.tar.gz |
Revert patch onto contrib/libs/curl
commit_hash:546bccba996bfcdfc752dfeb824bb663f6f48049
-rw-r--r-- | contrib/libs/curl/lib/asyn-thread.c | 228 | ||||
-rw-r--r-- | contrib/libs/curl/lib/multi.c | 6 |
2 files changed, 16 insertions, 218 deletions
diff --git a/contrib/libs/curl/lib/asyn-thread.c b/contrib/libs/curl/lib/asyn-thread.c index e44fe2c648..63414b6174 100644 --- a/contrib/libs/curl/lib/asyn-thread.c +++ b/contrib/libs/curl/lib/asyn-thread.c @@ -73,74 +73,23 @@ struct resdata { struct curltime start; }; -/* Doubly linked list of orphaned thread handles. */ -struct thread_list { - curl_thread_t handle; - - /* 'exiting' is set true right before an orphaned thread exits. - it should only be set by the orphaned thread from - signal_orphan_is_exiting(). */ - bool exiting; - - struct thread_list *prev, *next; -}; - -/* Orphaned threads: A global list of resolver threads that could not be - * completed in time and so they were abandoned by their parent. The list is - * culled periodically by soon-to-be exiting orphans to wait on and destroy - * those that are in the process of or have since exited, which is fast. On - * global cleanup we wait on and destroy any remaining threads, which may be - * slow but at that point we cannot defer it any longer. - */ -struct orphaned_threads { - /* Mutex to lock this. To avoid deadlock the thread-specific thread_sync_data - mutex cannot be used as an inner lock when orphaned_threads is locked. */ - curl_mutex_t mutex; - - /* List of orphaned threads. */ - struct thread_list *first, *last; - - /* Count of threads in the list that are in the process of or have exited. - (ie .exiting member of the thread_list item is set true) */ - size_t exiting_count; -}; - -static struct orphaned_threads orphaned_threads; - -/* Flags for wait_and_destroy_orphaned_threads(). - They're documented above the function definition. */ -#define WAIT_DESTROY_ALL (1<<0) -#define WAIT_DESTROY_EXITING_THREADS_ONLY (1<<1) - -static void wait_and_destroy_orphaned_threads(int flags); -static void signal_orphan_is_exiting(struct thread_list *orphan); - - /* * Curl_resolver_global_init() * Called from curl_global_init() to initialize global resolver environment. + * Does nothing here. */ int Curl_resolver_global_init(void) { - memset(&orphaned_threads, 0, sizeof(orphaned_threads)); - - if(Curl_mutex_init(&orphaned_threads.mutex)) - return CURLE_FAILED_INIT; - return CURLE_OK; } /* * Curl_resolver_global_cleanup() * Called from curl_global_cleanup() to destroy global resolver environment. + * Does nothing here. */ void Curl_resolver_global_cleanup(void) { - /* Take ownership of all orphaned resolver threads and wait for them to exit. - This is necessary because the user may choose to unload the shared library - that is/contains libcurl. */ - wait_and_destroy_orphaned_threads(WAIT_DESTROY_ALL); - Curl_mutex_destroy(&orphaned_threads.mutex); } /* @@ -220,8 +169,6 @@ struct thread_data { unsigned int poll_interval; timediff_t interval_end; struct thread_sync_data tsd; - /* 'reserved' memory must be available in case the thread is orphaned */ - void *reserved; }; static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data) @@ -283,11 +230,7 @@ int init_thread_sync_data(struct thread_data *td, if(!tsd->mtx) goto err_exit; - if(Curl_mutex_init(tsd->mtx)) { - free(tsd->mtx); - tsd->mtx = NULL; - goto err_exit; - } + Curl_mutex_init(tsd->mtx); #ifndef CURL_DISABLE_SOCKETPAIR /* create socket pair or pipe */ @@ -346,7 +289,6 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) { struct thread_sync_data *tsd = (struct thread_sync_data *)arg; struct thread_data *td = tsd->td; - struct thread_list *orphan = NULL; char service[12]; int rc; #ifndef CURL_DISABLE_SOCKETPAIR @@ -371,7 +313,6 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) /* too late, gotta clean up the mess */ Curl_mutex_release(tsd->mtx); destroy_thread_sync_data(tsd); - orphan = (struct thread_list *)td->reserved; free(td); } else { @@ -389,9 +330,6 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) Curl_mutex_release(tsd->mtx); } - if(orphan) - signal_orphan_is_exiting(orphan); - return 0; } @@ -404,7 +342,6 @@ static unsigned int CURL_STDCALL gethostbyname_thread(void *arg) { struct thread_sync_data *tsd = (struct thread_sync_data *)arg; struct thread_data *td = tsd->td; - struct thread_list *orphan = NULL; tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port); @@ -419,7 +356,6 @@ static unsigned int CURL_STDCALL gethostbyname_thread(void *arg) /* too late, gotta clean up the mess */ Curl_mutex_release(tsd->mtx); destroy_thread_sync_data(tsd); - orphan = (struct thread_list *)td->reserved; free(td); } else { @@ -427,9 +363,6 @@ static unsigned int CURL_STDCALL gethostbyname_thread(void *arg) Curl_mutex_release(tsd->mtx); } - if(orphan) - signal_orphan_is_exiting(orphan); - return 0; } @@ -448,60 +381,25 @@ static void destroy_async_data(struct Curl_async *async) struct Curl_easy *data = td->tsd.data; #endif - /* We can't wait any longer for the resolver thread so if it's not done - * then it must be orphaned. - * - * 1) add thread to orphaned threads list - * 2) set thread done (this signals to thread it has been orphaned) - * - * An orphaned thread does most of its own cleanup, and any remaining - * cleanup is handled during global cleanup. + /* + * if the thread is still blocking in the resolve syscall, detach it and + * let the thread do the cleanup... */ - Curl_mutex_acquire(td->tsd.mtx); - - if(!td->tsd.done && td->thread_hnd != curl_thread_t_null) { - struct thread_list *orphan = (struct thread_list *)td->reserved; - - Curl_mutex_acquire(&orphaned_threads.mutex); - -#ifdef DEBUGBUILD - { - struct thread_list empty; - memset(&empty, 0, sizeof(empty)); - DEBUGASSERT(!memcmp(&empty, orphan, sizeof(empty))); - } -#endif - - orphan->handle = td->thread_hnd; - orphan->exiting = false; - - if(orphaned_threads.last) { - orphaned_threads.last->next = orphan; - orphan->prev = orphaned_threads.last; - } - else { - orphaned_threads.first = orphan; - orphan->prev = NULL; - } - orphaned_threads.last = orphan; - orphan->next = NULL; - - Curl_mutex_release(&orphaned_threads.mutex); - } - done = td->tsd.done; td->tsd.done = 1; - Curl_mutex_release(td->tsd.mtx); - if(done) { + if(!done) { + Curl_thread_destroy(td->thread_hnd); + } + else { if(td->thread_hnd != curl_thread_t_null) Curl_thread_join(&td->thread_hnd); destroy_thread_sync_data(&td->tsd); - free(td->reserved); - free(td); + + free(async->tdata); } #ifndef CURL_DISABLE_SOCKETPAIR /* @@ -541,11 +439,9 @@ static bool init_resolve_thread(struct Curl_easy *data, asp->status = 0; asp->dns = NULL; td->thread_hnd = curl_thread_t_null; - td->reserved = calloc(1, sizeof(struct thread_list)); - if(!td->reserved || !init_thread_sync_data(td, hostname, port, hints)) { + if(!init_thread_sync_data(td, hostname, port, hints)) { asp->tdata = NULL; - free(td->reserved); free(td); goto errno_exit; } @@ -564,7 +460,7 @@ static bool init_resolve_thread(struct Curl_easy *data, td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd); #endif - if(td->thread_hnd == curl_thread_t_null) { + if(!td->thread_hnd) { /* The thread never started, so mark it as done here for proper cleanup. */ td->tsd.done = 1; err = errno; @@ -861,100 +757,4 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, return CURLE_NOT_BUILT_IN; } -/* Helper function to wait and destroy some or all orphaned threads. - * - * WAIT_DESTROY_ALL: - * Wait and destroy all orphaned threads. This operation is not safe to specify - * in code that could run in any thread that may be orphaned (ie any resolver - * thread). Waiting on all orphaned threads may take some time. This operation - * must be specified in the call from global cleanup, and ideally nowhere else. - * - * WAIT_DESTROY_EXITING_THREADS_ONLY: - * Wait and destroy only orphaned threads that are in the process of or have - * since exited (ie those with .exiting set true). This is fast. - * - * When the calling thread owns orphaned_threads.mutex it must not call this - * function or deadlock my occur. - */ -static void wait_and_destroy_orphaned_threads(int flags) -{ - struct thread_list *thread = NULL; - - Curl_mutex_acquire(&orphaned_threads.mutex); - - if((flags & WAIT_DESTROY_EXITING_THREADS_ONLY)) { - struct thread_list *p, *next; - struct thread_list *first = NULL, *last = NULL; - - if(!orphaned_threads.exiting_count) { - Curl_mutex_release(&orphaned_threads.mutex); - return; - } - - for(p = orphaned_threads.first; p; p = next) { - next = p->next; - - if(!p->exiting) - continue; - - /* remove thread list item from orphaned_threads */ - if(p->prev) - p->prev->next = p->next; - if(p->next) - p->next->prev = p->prev; - if(orphaned_threads.first == p) - orphaned_threads.first = p->next; - if(orphaned_threads.last == p) - orphaned_threads.last = p->prev; - - /* add thread list item to new thread list */ - if(last) { - last->next = p; - p->prev = last; - } - else { - first = p; - p->prev = NULL; - } - last = p; - p->next = NULL; - } - - thread = first; - orphaned_threads.exiting_count = 0; - } - else if((flags & WAIT_DESTROY_ALL)) { - thread = orphaned_threads.first; - orphaned_threads.first = NULL; - orphaned_threads.last = NULL; - orphaned_threads.exiting_count = 0; - } - - Curl_mutex_release(&orphaned_threads.mutex); - - /* Wait and free. Must be done unlocked or there could be deadlock. */ - while(thread) { - struct thread_list *next = thread->next; - Curl_thread_join(&thread->handle); - free(thread); - thread = next; - } -} - -/* Helper function that must be called from an orphaned thread right before it - exits. */ -static void signal_orphan_is_exiting(struct thread_list *orphan) -{ - DEBUGASSERT(orphan->handle && !orphan->exiting); - - wait_and_destroy_orphaned_threads(WAIT_DESTROY_EXITING_THREADS_ONLY); - - Curl_mutex_acquire(&orphaned_threads.mutex); - - orphan->exiting = true; - orphaned_threads.exiting_count++; - - Curl_mutex_release(&orphaned_threads.mutex); -} - #endif /* CURLRES_THREADED */ diff --git a/contrib/libs/curl/lib/multi.c b/contrib/libs/curl/lib/multi.c index 8051de0628..5456113be7 100644 --- a/contrib/libs/curl/lib/multi.c +++ b/contrib/libs/curl/lib/multi.c @@ -656,10 +656,8 @@ static CURLcode multi_done(struct Curl_easy *data, /* Stop if multi_done() has already been called */ return CURLE_OK; - /* Cancel the resolver (but not dns_entry yet). We used to call - Curl_resolver_kill here but that blocks waiting for incomplete resolve - threads (eg getaddrinfo has not returned), which may take a while. */ - Curl_resolver_cancel(data); + /* Stop the resolver and free its own resources (but not dns_entry yet). */ + Curl_resolver_kill(data); /* Cleanup possible redirect junk */ Curl_safefree(data->req.newurl); |