From: Waldemar Zimpel Date: Sun, 24 Aug 2025 19:10:34 +0000 (+0200) Subject: Make thread control POSIX compliant X-Git-Tag: tor-0.4.8.18~8^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2263bb73cc478fee3ef0ff949723a02c84766312;p=thirdparty%2Ftor.git Make thread control POSIX compliant Closes issue #41109 --- diff --git a/changes/bug41109 b/changes/bug41109 new file mode 100644 index 0000000000..65d962787b --- /dev/null +++ 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 index 59a6cf13cd..f8a5cb87e9 100644 --- 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 @@ -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; }