From bd461eb92048d7dd13ba25dbdafb1fd5440c071c Mon Sep 17 00:00:00 2001 From: Waldemar Zimpel Date: Sun, 24 Aug 2025 21:10:34 +0200 Subject: [PATCH] Make thread control POSIX compliant Closes issue #41109 --- changes/bug41109 | 3 +++ src/lib/evloop/workqueue.c | 31 +++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 changes/bug41109 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..60b22016b1 100644 --- a/src/lib/evloop/workqueue.c +++ b/src/lib/evloop/workqueue.c @@ -278,6 +278,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 +298,11 @@ worker_thread_main(void *thread_) * pool->lock must be prelocked here. */ tor_mutex_acquire(&pool->lock); + if (control_lock_owner == 0) { + 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 +368,25 @@ 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) { + if (n_worker_threads_running > 1) { + /* Wait for the other worker threads to exit so we + * can safely unlock pool->control_lock. */ + struct timespec ts = {.tv_sec = 0, .tv_nsec = 100000}; + do { + tor_mutex_release(&pool->lock); + nanosleep(&ts, NULL); + tor_mutex_acquire(&pool->lock); + } while (n_worker_threads_running > 1); + } + + 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 @@ -621,12 +641,11 @@ check_status: log_debug(LD_GENERAL, "Signaled the worker threads to exit..."); } + /* Let one of the worker threads take the ownership of pool->control_lock */ + tor_mutex_release(&pool->control_lock); /* 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. */ - return status; } -- 2.47.3