tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

commit dd92906c0ff9e753b4586c50deae420d128a4aef
parent 45edc59caa435d2bcd444ebeb40fc822d5629978
Author: David Goulet <dgoulet@torproject.org>
Date:   Wed, 10 Sep 2025 13:07:16 -0400

Merge branch 'maint-0.4.8'

Diffstat:
Achanges/bug41109 | 3+++
Msrc/lib/evloop/workqueue.c | 33+++++++++++++++++++++++++++------
Msrc/lib/time/compat_time.c | 9+++++----
Msrc/lib/time/compat_time.h | 4++--
4 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/changes/bug41109 b/changes/bug41109 @@ -0,0 +1,3 @@ + o Minor bugfixes (threads): + - Make thread control POSIX compliant. + Fixes bug 41109; bugfix on 0.4.8.17-dev. diff --git a/src/lib/evloop/workqueue.c b/src/lib/evloop/workqueue.c @@ -38,6 +38,7 @@ #include "lib/net/alertsock.h" #include "lib/net/socket.h" #include "lib/thread/threads.h" +#include "lib/time/compat_time.h" #include "ext/tor_queue.h" #include <event2/event.h> @@ -278,6 +279,7 @@ static void worker_thread_main(void *thread_) { static int n_worker_threads_running = 0; + static unsigned long control_lock_owner = 0; workerthread_t *thread = thread_; threadpool_t *pool = thread->in_pool; workqueue_entry_t *work; @@ -297,6 +299,14 @@ worker_thread_main(void *thread_) * pool->lock must be prelocked here. */ tor_mutex_acquire(&pool->lock); + if (control_lock_owner == 0) { + /* pool->control_lock stays locked. This is required for the main thread + * to wait for the worker threads to exit on shutdown, so the memory + * clean up won't begin before all threads have exited. */ + tor_mutex_acquire(&pool->control_lock); + control_lock_owner = tor_get_thread_id(); + } + log_debug(LD_GENERAL, "Worker thread has entered the work loop [TID: %lu].", tor_get_thread_id()); @@ -362,11 +372,22 @@ exit: pool->n_threads_max - n_worker_threads_running + 1, pool->n_threads_max, tor_get_thread_id()); - if (--n_worker_threads_running == 0) + if (tor_get_thread_id() == control_lock_owner) { + /* Wait for the other worker threads to exit so we + * can safely unlock pool->control_lock. */ + while (n_worker_threads_running > 1) { + tor_mutex_release(&pool->lock); + tor_sleep_msec(10); + tor_mutex_acquire(&pool->lock); + } + + tor_mutex_release(&pool->lock); /* Let the main thread know, the last worker thread has exited. */ tor_mutex_release(&pool->control_lock); - - tor_mutex_release(&pool->lock); + } else { + --n_worker_threads_running; + tor_mutex_release(&pool->lock); + } } /** Put a reply on the reply queue. The reply must not currently be on @@ -623,9 +644,9 @@ check_status: /* Let worker threads enter the work loop. */ tor_mutex_release(&pool->lock); - - /* pool->control_lock stays locked. This is required for the main thread - * to wait for the worker threads to exit on shutdown. */ + /* Let one of the worker threads take the ownership of pool->control_lock. + * This is required for compliance with POSIX. */ + tor_mutex_release(&pool->control_lock); return status; } diff --git a/src/lib/time/compat_time.c b/src/lib/time/compat_time.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ + * Copyright (c) 2007-2025, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -53,13 +53,15 @@ #undef HAVE_CLOCK_GETTIME #endif -#ifdef TOR_UNIT_TESTS -/** Delay for <b>msec</b> milliseconds. Only used in tests. */ +/** Delay for <b>msec</b> milliseconds. */ void tor_sleep_msec(int msec) { #ifdef _WIN32 Sleep(msec); +#elif defined(HAVE_TIME_H) + struct timespec ts = {msec / 1000, (msec % 1000) * 1000 * 1000}; + while (nanosleep(&ts, &ts) == -1 && errno == EINTR); #elif defined(HAVE_USLEEP) sleep(msec / 1000); /* Some usleep()s hate sleeping more than 1 sec */ @@ -71,7 +73,6 @@ tor_sleep_msec(int msec) sleep(CEIL_DIV(msec, 1000)); #endif /* defined(_WIN32) || ... */ } -#endif /* defined(TOR_UNIT_TESTS) */ #define ONE_MILLION ((int64_t) (1000 * 1000)) #define ONE_BILLION ((int64_t) (1000 * 1000 * 1000)) diff --git a/src/lib/time/compat_time.h b/src/lib/time/compat_time.h @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ + * Copyright (c) 2007-2025, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -361,9 +361,9 @@ monotime_coarse_diff_msec32(const monotime_coarse_t *start, #endif /* SIZEOF_VOID_P == 8 */ } -#ifdef TOR_UNIT_TESTS void tor_sleep_msec(int msec); +#ifdef TOR_UNIT_TESTS void monotime_enable_test_mocking(void); void monotime_disable_test_mocking(void); void monotime_set_mock_time_nsec(int64_t);