]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
lib: Fix undefined behaviour at fork time in pthreadpool
authorVolker Lendecke <vl@samba.org>
Tue, 28 Jul 2026 11:25:43 +0000 (13:25 +0200)
committerVolker Lendecke <vl@samba.org>
Thu, 30 Jul 2026 17:51:29 +0000 (17:51 +0000)
If a pthread times out at the same time with a fork, ETIMEDOUT is
overwritten and not being taken care of. This means that we can race
with the forking thread destroying pool->condvar in the next round of
the thread's while(1) loop. pthread_cond_wait() on a condition
variable that has been destroyed is not a good idea.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=16191

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Autobuild-User(master): Volker Lendecke <vl@samba.org>
Autobuild-Date(master): Thu Jul 30 17:51:29 UTC 2026 on atb-devel-224

lib/pthreadpool/pthreadpool.c

index cbabec9e25d06b366a0a73e5055226ec288435f5..7529fe10c72262cec98f8b2d94c9589a84fc4a44 100644 (file)
@@ -591,8 +591,10 @@ static void *pthreadpool_server(void *arg)
 
                while ((pool->num_jobs == 0) && !pool->stopped) {
 
+                       int wait_res;
+
                        pool->num_idle += 1;
-                       res = pthread_cond_timedwait(
+                       wait_res = pthread_cond_timedwait(
                                &pool->condvar, &pool->mutex, &ts);
                        pool->num_idle -= 1;
 
@@ -626,7 +628,7 @@ static void *pthreadpool_server(void *arg)
                                assert(res == 0);
                        }
 
-                       if (res == ETIMEDOUT) {
+                       if (wait_res == ETIMEDOUT) {
 
                                if (pool->num_jobs == 0) {
                                        /*
@@ -639,7 +641,7 @@ static void *pthreadpool_server(void *arg)
 
                                break;
                        }
-                       assert(res == 0);
+                       assert(wait_res == 0);
                }
 
                if (pthreadpool_get_job(pool, &job)) {