]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Make thread control POSIX compliant
authorWaldemar Zimpel <w.zimpel@dev.utilizer.de>
Sun, 24 Aug 2025 19:10:34 +0000 (21:10 +0200)
committerWaldemar Zimpel <w.zimpel@dev.utilizer.de>
Sun, 24 Aug 2025 19:10:34 +0000 (21:10 +0200)
Closes issue #41109

changes/bug41109 [new file with mode: 0644]
src/lib/evloop/workqueue.c

diff --git a/changes/bug41109 b/changes/bug41109
new file mode 100644 (file)
index 0000000..65d9627
--- /dev/null
@@ -0,0 +1,3 @@
+  o Minor bugfixes (threads):
+    - Make thread control POSIX compliant.
+      Fixes bug 41109; bugfix on 0.4.8.17-dev.
index 59a6cf13cdc18a845b8259dd9944cd5ff1f34424..60b22016b1e162aa6e080ec24c5ee5bc49d40732 100644 (file)
@@ -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;
 }