tor

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

commit 2263bb73cc478fee3ef0ff949723a02c84766312
parent 78a7a6e2525f4a22253ddc3dcd2ce7df7d819591
Author: Waldemar Zimpel <w.zimpel@dev.utilizer.de>
Date:   Sun, 24 Aug 2025 21:10:34 +0200

Make thread control POSIX compliant

Closes issue #41109

Diffstat:
Achanges/bug41109 | 3+++
Msrc/lib/evloop/workqueue.c | 33+++++++++++++++++++++++++++------
2 files changed, 30 insertions(+), 6 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; }