From 209e7077bb9fb3da99873f2bf7eec70f4be37117 Mon Sep 17 00:00:00 2001 From: Brad House Date: Sun, 23 Jun 2024 13:55:57 -0400 Subject: [PATCH] thread safety enhancements --- docs/ares_init_options.3 | 5 +++-- src/lib/ares_event_thread.c | 11 +++++++---- src/lib/ares_private.h | 2 -- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/ares_init_options.3 b/docs/ares_init_options.3 index db24c05e..c31b1edf 100644 --- a/docs/ares_init_options.3 +++ b/docs/ares_init_options.3 @@ -227,8 +227,9 @@ The value of .I sock_state_cb_data will be passed as the .I data -argument. Since this may be called cross-thread, a channel lock is NOT held -when this callback is called. +argument. The channel lock is held during this callback, if calling +cross-thread care must be taken to ensure no other c-ares functions are +called from this callback. Cannot be used with \fBARES_OPT_EVENT_THREAD\fP. .TP 18 diff --git a/src/lib/ares_event_thread.c b/src/lib/ares_event_thread.c index 4406be2a..3f96e2e6 100644 --- a/src/lib/ares_event_thread.c +++ b/src/lib/ares_event_thread.c @@ -274,16 +274,19 @@ static void *ares_event_thread(void *arg) const struct timeval *tvout; unsigned long timeout_ms = 0; /* 0 = unlimited */ + ares_event_process_updates(e); + + /* Don't hold a mutex while waiting on events or calling into anything + * that might require a c-ares channel lock since a callback could be + * triggered cross-thread */ + ares__thread_mutex_unlock(e->mutex); + tvout = ares_timeout(e->channel, NULL, &tv); if (tvout != NULL) { timeout_ms = (unsigned long)((tvout->tv_sec * 1000) + (tvout->tv_usec / 1000) + 1); } - ares_event_process_updates(e); - - /* Don't hold a mutex while waiting on events */ - ares__thread_mutex_unlock(e->mutex); e->ev_sys->wait(e, timeout_ms); /* Each iteration should do timeout processing */ diff --git a/src/lib/ares_private.h b/src/lib/ares_private.h index 0556eefa..5015923c 100644 --- a/src/lib/ares_private.h +++ b/src/lib/ares_private.h @@ -667,9 +667,7 @@ void ares_queue_notify_empty(ares_channel_t *channel); #define SOCK_STATE_CALLBACK(c, s, r, w) \ do { \ if ((c)->sock_state_cb) { \ - ares__channel_unlock((c)); \ (c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w)); \ - ares__channel_lock((c)); \ } \ } while (0)