asyn-thrdd: use condition var more carefully

When the thread started is too fast, the signal will come before the
wait. Add an additional check before the wait to catch the thread
having started or already ended.

Closes #18344
This commit is contained in:
Stefan Eissing 2025-08-21 21:19:27 +02:00 committed by Daniel Stenberg
parent b6a5f67259
commit bd4622bfaf
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
2 changed files with 18 additions and 6 deletions

View file

@ -135,6 +135,13 @@ static void addr_ctx_unlink(struct async_thrdd_addr_ctx **paddr_ctx,
#ifndef CURL_DISABLE_SOCKETPAIR
if(!destroy) {
if(!data) { /* Called from thread, transfer still waiting on results. */
/* Mark thread as done and signal the condition again, in case the
* one waiting missed our fist signal at the start. */
addr_ctx->thrd_done = TRUE;
#ifdef USE_CURL_COND_T
Curl_cond_signal(&addr_ctx->cond);
#endif
if(addr_ctx->sock_pair[1] != CURL_SOCKET_BAD) {
#ifdef USE_EVENTFD
const uint64_t buf[1] = { 1 };
@ -379,7 +386,7 @@ static void async_thrdd_destroy(struct Curl_easy *data)
bool done = TRUE;
Curl_mutex_acquire(&addr->mutx);
done = (addr->ref_count <= 1);
done = addr->thrd_done;
Curl_mutex_release(&addr->mutx);
if(done) {
Curl_thread_join(&addr->thread_hnd);
@ -504,9 +511,13 @@ static bool async_thrdd_init(struct Curl_easy *data,
}
else {
#ifdef USE_CURL_COND_T
/* need to handshake with thread for participation in ref counting */
Curl_cond_wait(&addr_ctx->cond, &addr_ctx->mutx);
DEBUGASSERT(addr_ctx->ref_count >= 1);
/* need to handshake with thread for participation in ref counting.
* We wait to see the thread having incremented `ref_count`, so it
* started. However it may run to its end before we get the
* signal, in which case `ref_count` is 1 again, but then
* `thrd_done` is TRUE.*/
while((addr_ctx->ref_count <= 1) && !addr_ctx->thrd_done)
Curl_cond_wait(&addr_ctx->cond, &addr_ctx->mutx);
#endif
Curl_mutex_release(&addr_ctx->mutx);
}
@ -537,7 +548,7 @@ static void async_thrdd_shutdown(struct Curl_easy *data)
return;
Curl_mutex_acquire(&addr_ctx->mutx);
done = (addr_ctx->ref_count <= 1);
done = addr_ctx->thrd_done;
/* We are no longer interested in wakeups */
if(addr_ctx->sock_pair[1] != CURL_SOCKET_BAD) {
wakeup_close(addr_ctx->sock_pair[1]);
@ -660,7 +671,7 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data,
return CURLE_FAILED_INIT;
Curl_mutex_acquire(&thrdd->addr->mutx);
done = (thrdd->addr->ref_count == 1);
done = thrdd->addr->thrd_done;
Curl_mutex_release(&thrdd->addr->mutx);
if(done) {

View file

@ -196,6 +196,7 @@ struct async_thrdd_addr_ctx {
int port;
int sock_error;
int ref_count;
BIT(thrd_done);
};
/* Context for threaded resolver */