Skip to content

Commit 2084bac

Browse files
committed
Revert patch onto contrib/libs/curl
commit_hash:546bccba996bfcdfc752dfeb824bb663f6f48049
1 parent a830a77 commit 2084bac

File tree

2 files changed

+16
-218
lines changed

2 files changed

+16
-218
lines changed

contrib/libs/curl/lib/asyn-thread.c

Lines changed: 14 additions & 214 deletions
Original file line numberDiff line numberDiff line change
@@ -73,74 +73,23 @@ struct resdata {
7373
struct curltime start;
7474
};
7575

76-
/* Doubly linked list of orphaned thread handles. */
77-
struct thread_list {
78-
curl_thread_t handle;
79-
80-
/* 'exiting' is set true right before an orphaned thread exits.
81-
it should only be set by the orphaned thread from
82-
signal_orphan_is_exiting(). */
83-
bool exiting;
84-
85-
struct thread_list *prev, *next;
86-
};
87-
88-
/* Orphaned threads: A global list of resolver threads that could not be
89-
* completed in time and so they were abandoned by their parent. The list is
90-
* culled periodically by soon-to-be exiting orphans to wait on and destroy
91-
* those that are in the process of or have since exited, which is fast. On
92-
* global cleanup we wait on and destroy any remaining threads, which may be
93-
* slow but at that point we cannot defer it any longer.
94-
*/
95-
struct orphaned_threads {
96-
/* Mutex to lock this. To avoid deadlock the thread-specific thread_sync_data
97-
mutex cannot be used as an inner lock when orphaned_threads is locked. */
98-
curl_mutex_t mutex;
99-
100-
/* List of orphaned threads. */
101-
struct thread_list *first, *last;
102-
103-
/* Count of threads in the list that are in the process of or have exited.
104-
(ie .exiting member of the thread_list item is set true) */
105-
size_t exiting_count;
106-
};
107-
108-
static struct orphaned_threads orphaned_threads;
109-
110-
/* Flags for wait_and_destroy_orphaned_threads().
111-
They're documented above the function definition. */
112-
#define WAIT_DESTROY_ALL (1<<0)
113-
#define WAIT_DESTROY_EXITING_THREADS_ONLY (1<<1)
114-
115-
static void wait_and_destroy_orphaned_threads(int flags);
116-
static void signal_orphan_is_exiting(struct thread_list *orphan);
117-
118-
11976
/*
12077
* Curl_resolver_global_init()
12178
* Called from curl_global_init() to initialize global resolver environment.
79+
* Does nothing here.
12280
*/
12381
int Curl_resolver_global_init(void)
12482
{
125-
memset(&orphaned_threads, 0, sizeof(orphaned_threads));
126-
127-
if(Curl_mutex_init(&orphaned_threads.mutex))
128-
return CURLE_FAILED_INIT;
129-
13083
return CURLE_OK;
13184
}
13285

13386
/*
13487
* Curl_resolver_global_cleanup()
13588
* Called from curl_global_cleanup() to destroy global resolver environment.
89+
* Does nothing here.
13690
*/
13791
void Curl_resolver_global_cleanup(void)
13892
{
139-
/* Take ownership of all orphaned resolver threads and wait for them to exit.
140-
This is necessary because the user may choose to unload the shared library
141-
that is/contains libcurl. */
142-
wait_and_destroy_orphaned_threads(WAIT_DESTROY_ALL);
143-
Curl_mutex_destroy(&orphaned_threads.mutex);
14493
}
14594

14695
/*
@@ -220,8 +169,6 @@ struct thread_data {
220169
unsigned int poll_interval;
221170
timediff_t interval_end;
222171
struct thread_sync_data tsd;
223-
/* 'reserved' memory must be available in case the thread is orphaned */
224-
void *reserved;
225172
};
226173

227174
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,
283230
if(!tsd->mtx)
284231
goto err_exit;
285232

286-
if(Curl_mutex_init(tsd->mtx)) {
287-
free(tsd->mtx);
288-
tsd->mtx = NULL;
289-
goto err_exit;
290-
}
233+
Curl_mutex_init(tsd->mtx);
291234

292235
#ifndef CURL_DISABLE_SOCKETPAIR
293236
/* create socket pair or pipe */
@@ -346,7 +289,6 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
346289
{
347290
struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
348291
struct thread_data *td = tsd->td;
349-
struct thread_list *orphan = NULL;
350292
char service[12];
351293
int rc;
352294
#ifndef CURL_DISABLE_SOCKETPAIR
@@ -371,7 +313,6 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
371313
/* too late, gotta clean up the mess */
372314
Curl_mutex_release(tsd->mtx);
373315
destroy_thread_sync_data(tsd);
374-
orphan = (struct thread_list *)td->reserved;
375316
free(td);
376317
}
377318
else {
@@ -389,9 +330,6 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
389330
Curl_mutex_release(tsd->mtx);
390331
}
391332

392-
if(orphan)
393-
signal_orphan_is_exiting(orphan);
394-
395333
return 0;
396334
}
397335

@@ -404,7 +342,6 @@ static unsigned int CURL_STDCALL gethostbyname_thread(void *arg)
404342
{
405343
struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
406344
struct thread_data *td = tsd->td;
407-
struct thread_list *orphan = NULL;
408345

409346
tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port);
410347

@@ -419,17 +356,13 @@ static unsigned int CURL_STDCALL gethostbyname_thread(void *arg)
419356
/* too late, gotta clean up the mess */
420357
Curl_mutex_release(tsd->mtx);
421358
destroy_thread_sync_data(tsd);
422-
orphan = (struct thread_list *)td->reserved;
423359
free(td);
424360
}
425361
else {
426362
tsd->done = 1;
427363
Curl_mutex_release(tsd->mtx);
428364
}
429365

430-
if(orphan)
431-
signal_orphan_is_exiting(orphan);
432-
433366
return 0;
434367
}
435368

@@ -448,60 +381,25 @@ static void destroy_async_data(struct Curl_async *async)
448381
struct Curl_easy *data = td->tsd.data;
449382
#endif
450383

451-
/* We can't wait any longer for the resolver thread so if it's not done
452-
* then it must be orphaned.
453-
*
454-
* 1) add thread to orphaned threads list
455-
* 2) set thread done (this signals to thread it has been orphaned)
456-
*
457-
* An orphaned thread does most of its own cleanup, and any remaining
458-
* cleanup is handled during global cleanup.
384+
/*
385+
* if the thread is still blocking in the resolve syscall, detach it and
386+
* let the thread do the cleanup...
459387
*/
460-
461388
Curl_mutex_acquire(td->tsd.mtx);
462-
463-
if(!td->tsd.done && td->thread_hnd != curl_thread_t_null) {
464-
struct thread_list *orphan = (struct thread_list *)td->reserved;
465-
466-
Curl_mutex_acquire(&orphaned_threads.mutex);
467-
468-
#ifdef DEBUGBUILD
469-
{
470-
struct thread_list empty;
471-
memset(&empty, 0, sizeof(empty));
472-
DEBUGASSERT(!memcmp(&empty, orphan, sizeof(empty)));
473-
}
474-
#endif
475-
476-
orphan->handle = td->thread_hnd;
477-
orphan->exiting = false;
478-
479-
if(orphaned_threads.last) {
480-
orphaned_threads.last->next = orphan;
481-
orphan->prev = orphaned_threads.last;
482-
}
483-
else {
484-
orphaned_threads.first = orphan;
485-
orphan->prev = NULL;
486-
}
487-
orphaned_threads.last = orphan;
488-
orphan->next = NULL;
489-
490-
Curl_mutex_release(&orphaned_threads.mutex);
491-
}
492-
493389
done = td->tsd.done;
494390
td->tsd.done = 1;
495-
496391
Curl_mutex_release(td->tsd.mtx);
497392

498-
if(done) {
393+
if(!done) {
394+
Curl_thread_destroy(td->thread_hnd);
395+
}
396+
else {
499397
if(td->thread_hnd != curl_thread_t_null)
500398
Curl_thread_join(&td->thread_hnd);
501399

502400
destroy_thread_sync_data(&td->tsd);
503-
free(td->reserved);
504-
free(td);
401+
402+
free(async->tdata);
505403
}
506404
#ifndef CURL_DISABLE_SOCKETPAIR
507405
/*
@@ -541,11 +439,9 @@ static bool init_resolve_thread(struct Curl_easy *data,
541439
asp->status = 0;
542440
asp->dns = NULL;
543441
td->thread_hnd = curl_thread_t_null;
544-
td->reserved = calloc(1, sizeof(struct thread_list));
545442

546-
if(!td->reserved || !init_thread_sync_data(td, hostname, port, hints)) {
443+
if(!init_thread_sync_data(td, hostname, port, hints)) {
547444
asp->tdata = NULL;
548-
free(td->reserved);
549445
free(td);
550446
goto errno_exit;
551447
}
@@ -564,7 +460,7 @@ static bool init_resolve_thread(struct Curl_easy *data,
564460
td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd);
565461
#endif
566462

567-
if(td->thread_hnd == curl_thread_t_null) {
463+
if(!td->thread_hnd) {
568464
/* The thread never started, so mark it as done here for proper cleanup. */
569465
td->tsd.done = 1;
570466
err = errno;
@@ -861,100 +757,4 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
861757
return CURLE_NOT_BUILT_IN;
862758
}
863759

864-
/* Helper function to wait and destroy some or all orphaned threads.
865-
*
866-
* WAIT_DESTROY_ALL:
867-
* Wait and destroy all orphaned threads. This operation is not safe to specify
868-
* in code that could run in any thread that may be orphaned (ie any resolver
869-
* thread). Waiting on all orphaned threads may take some time. This operation
870-
* must be specified in the call from global cleanup, and ideally nowhere else.
871-
*
872-
* WAIT_DESTROY_EXITING_THREADS_ONLY:
873-
* Wait and destroy only orphaned threads that are in the process of or have
874-
* since exited (ie those with .exiting set true). This is fast.
875-
*
876-
* When the calling thread owns orphaned_threads.mutex it must not call this
877-
* function or deadlock my occur.
878-
*/
879-
static void wait_and_destroy_orphaned_threads(int flags)
880-
{
881-
struct thread_list *thread = NULL;
882-
883-
Curl_mutex_acquire(&orphaned_threads.mutex);
884-
885-
if((flags & WAIT_DESTROY_EXITING_THREADS_ONLY)) {
886-
struct thread_list *p, *next;
887-
struct thread_list *first = NULL, *last = NULL;
888-
889-
if(!orphaned_threads.exiting_count) {
890-
Curl_mutex_release(&orphaned_threads.mutex);
891-
return;
892-
}
893-
894-
for(p = orphaned_threads.first; p; p = next) {
895-
next = p->next;
896-
897-
if(!p->exiting)
898-
continue;
899-
900-
/* remove thread list item from orphaned_threads */
901-
if(p->prev)
902-
p->prev->next = p->next;
903-
if(p->next)
904-
p->next->prev = p->prev;
905-
if(orphaned_threads.first == p)
906-
orphaned_threads.first = p->next;
907-
if(orphaned_threads.last == p)
908-
orphaned_threads.last = p->prev;
909-
910-
/* add thread list item to new thread list */
911-
if(last) {
912-
last->next = p;
913-
p->prev = last;
914-
}
915-
else {
916-
first = p;
917-
p->prev = NULL;
918-
}
919-
last = p;
920-
p->next = NULL;
921-
}
922-
923-
thread = first;
924-
orphaned_threads.exiting_count = 0;
925-
}
926-
else if((flags & WAIT_DESTROY_ALL)) {
927-
thread = orphaned_threads.first;
928-
orphaned_threads.first = NULL;
929-
orphaned_threads.last = NULL;
930-
orphaned_threads.exiting_count = 0;
931-
}
932-
933-
Curl_mutex_release(&orphaned_threads.mutex);
934-
935-
/* Wait and free. Must be done unlocked or there could be deadlock. */
936-
while(thread) {
937-
struct thread_list *next = thread->next;
938-
Curl_thread_join(&thread->handle);
939-
free(thread);
940-
thread = next;
941-
}
942-
}
943-
944-
/* Helper function that must be called from an orphaned thread right before it
945-
exits. */
946-
static void signal_orphan_is_exiting(struct thread_list *orphan)
947-
{
948-
DEBUGASSERT(orphan->handle && !orphan->exiting);
949-
950-
wait_and_destroy_orphaned_threads(WAIT_DESTROY_EXITING_THREADS_ONLY);
951-
952-
Curl_mutex_acquire(&orphaned_threads.mutex);
953-
954-
orphan->exiting = true;
955-
orphaned_threads.exiting_count++;
956-
957-
Curl_mutex_release(&orphaned_threads.mutex);
958-
}
959-
960760
#endif /* CURLRES_THREADED */

contrib/libs/curl/lib/multi.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -656,10 +656,8 @@ static CURLcode multi_done(struct Curl_easy *data,
656656
/* Stop if multi_done() has already been called */
657657
return CURLE_OK;
658658

659-
/* Cancel the resolver (but not dns_entry yet). We used to call
660-
Curl_resolver_kill here but that blocks waiting for incomplete resolve
661-
threads (eg getaddrinfo has not returned), which may take a while. */
662-
Curl_resolver_cancel(data);
659+
/* Stop the resolver and free its own resources (but not dns_entry yet). */
660+
Curl_resolver_kill(data);
663661

664662
/* Cleanup possible redirect junk */
665663
Curl_safefree(data->req.newurl);

0 commit comments

Comments
 (0)