Commit 26df7f3613 for frr
commit 26df7f3613558019b897006f1e7e21df4f045f2e
Author: Christian Hopps <chopps@labn.net>
Date: Sat Oct 10 05:09:19 2026 -0400
lib: need lock to make thread safe
Without the lock if multiple external threads all call rcu_thread_new()
in parallel we can end up with more than 1 call to rcu_start().
Signed-off-by: Christian Hopps <chopps@labn.net>
diff --git a/lib/frrcu.c b/lib/frrcu.c
index fea1731b2b..1d2f78620d 100644
--- a/lib/frrcu.c
+++ b/lib/frrcu.c
@@ -111,6 +111,7 @@ static struct rcu_thread rcu_thread_main;
static struct rcu_thread rcu_thread_rcu;
static pthread_t rcu_pthread;
+static pthread_mutex_t rcu_start_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_key_t rcu_thread_key;
static bool rcu_active;
@@ -158,10 +159,14 @@ struct rcu_thread *rcu_thread_new(void *arg)
struct rcu_thread *rt, *cur = arg;
/* Ensure the sweeper exists so deferred frees from thread teardown
- * (and any RCU use on the new thread) actually complete.
+ * (and any RCU use on the new thread) actually complete. External
+ * threads may register concurrently, so serialize the check + start,
+ * otherwise more than one sweeper gets started.
*/
+ pthread_mutex_lock(&rcu_start_mtx);
if (!rcu_active)
rcu_start();
+ pthread_mutex_unlock(&rcu_start_mtx);
/* new thread always starts with rcu_read_lock held at depth 1, and
* holding the same epoch as the parent (this makes it possible to