From: James Rouzier Date: Tue, 28 Oct 2014 21:13:43 +0000 (-0400) Subject: Lock thread_pool.wait_mutex before forking to avoid a race condition between rad_fork... X-Git-Tag: release_2_2_6~15^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F824%2Fhead;p=thirdparty%2Ffreeradius-server.git Lock thread_pool.wait_mutex before forking to avoid a race condition between rad_fork, rad_waitpid and reap_children. There is a race condition that can occur under high load where a child is reaped before being added to the waiters list. --- diff --git a/src/main/threads.c b/src/main/threads.c index 72d849fc03..d4de4ff436 100644 --- a/src/main/threads.c +++ b/src/main/threads.c @@ -1142,6 +1142,7 @@ pid_t rad_fork(void) /* * Fork & save the PID for later reaping. */ + pthread_mutex_lock(&thread_pool.wait_mutex); child_pid = fork(); if (child_pid > 0) { int rcode; @@ -1152,9 +1153,7 @@ pid_t rad_fork(void) tf->pid = child_pid; - pthread_mutex_lock(&thread_pool.wait_mutex); rcode = fr_hash_table_insert(thread_pool.waiters, tf); - pthread_mutex_unlock(&thread_pool.wait_mutex); if (!rcode) { radlog(L_ERR, "Failed to store PID, creating what will be a zombie process %d", @@ -1162,6 +1161,12 @@ pid_t rad_fork(void) free(tf); } } + /* + * Do not unlock in child process + */ + if(child_pid != 0 ) { + pthread_mutex_unlock(&thread_pool.wait_mutex); + } /* * Return whatever we were told.