The branch, master has been updated
       via  a7a77e2 tdb: avoid a race condition when checking for robust mutexes
      from  aa81199 vfs_glusterfs: call clock_gettime_mono() only on 
profile-enabled build

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit a7a77e2f43a5baa00e104037b20487f28aabe866
Author: Ralph Boehme <[email protected]>
Date:   Sat Mar 26 12:43:55 2016 +0100

    tdb: avoid a race condition when checking for robust mutexes
    
    This fixes a race between calling waitpid() in two places (SIGCHLD the
    signal handler and the rendezvous code when waiting for the child to
    terminate), by
    
    - blocking SIGCHLD before installing our signal handler
    
    - in the rendezvous code call sigssuspend() which unblocks SIGCHLD and
      suspends the thread and waits for signal delivery
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11808
    
    Signed-off-by: Ralph Boehme <[email protected]>
    Reviewed-by: Uri Simchoni <[email protected]>
    
    Autobuild-User(master): Ralph Böhme <[email protected]>
    Autobuild-Date(master): Tue Mar 29 16:04:19 CEST 2016 on sn-devel-144

-----------------------------------------------------------------------

Summary of changes:
 lib/tdb/common/mutex.c | 60 +++++++++++++++++++++++++++-----------------------
 1 file changed, 32 insertions(+), 28 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/tdb/common/mutex.c b/lib/tdb/common/mutex.c
index fae43d4..e57031d 100644
--- a/lib/tdb/common/mutex.c
+++ b/lib/tdb/common/mutex.c
@@ -775,8 +775,8 @@ _PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
        ssize_t nread;
        char c = 0;
        bool ok;
-       int status;
        static bool initialized;
+       sigset_t mask, old_mask, suspend_mask;
 
        if (initialized) {
                return tdb_mutex_locking_cached;
@@ -828,9 +828,22 @@ _PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
                goto cleanup_ma;
        }
 
+       /*
+        * Block SIGCHLD so we can atomically wait for it later with
+        * sigsuspend()
+        */
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGCHLD);
+       ret = pthread_sigmask(SIG_BLOCK, &mask, &old_mask);
+       if (ret != 0) {
+               goto cleanup_m;
+       }
+       suspend_mask = old_mask;
+       sigdelset(&suspend_mask, SIGCHLD);
+
        if (tdb_robust_mutex_setup_sigchild(tdb_robust_mutex_handler,
                        &tdb_robust_mutext_old_handler) == false) {
-               goto cleanup_ma;
+               goto cleanup_sigmask;
        }
 
        tdb_robust_mutex_pid = fork();
@@ -884,16 +897,9 @@ _PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
        }
 
        while (tdb_robust_mutex_pid > 0) {
-               pid_t pid;
-
-               errno = 0;
-               pid = waitpid(tdb_robust_mutex_pid, &status, 0);
-               if (pid == tdb_robust_mutex_pid) {
-                       tdb_robust_mutex_pid = -1;
-                       break;
-               }
-               if (pid == -1 && errno != EINTR) {
-                       goto cleanup_child;
+               ret = sigsuspend(&suspend_mask);
+               if (ret != -1 || errno != EINTR) {
+                       abort();
                }
        }
        tdb_robust_mutex_setup_sigchild(tdb_robust_mutext_old_handler, NULL);
@@ -903,46 +909,44 @@ _PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
                if (ret == 0) {
                        pthread_mutex_unlock(m);
                }
-               goto cleanup_m;
+               goto cleanup_sigmask;
        }
 
        ret = pthread_mutex_consistent(m);
        if (ret != 0) {
-               goto cleanup_m;
+               goto cleanup_sigmask;
        }
 
        ret = pthread_mutex_trylock(m);
        if (ret != EDEADLK) {
                pthread_mutex_unlock(m);
-               goto cleanup_m;
+               goto cleanup_sigmask;
        }
 
        ret = pthread_mutex_unlock(m);
        if (ret != 0) {
-               goto cleanup_m;
+               goto cleanup_sigmask;
        }
 
        tdb_mutex_locking_cached = true;
-       goto cleanup_m;
+       goto cleanup_sigmask;
 
 cleanup_child:
        while (tdb_robust_mutex_pid > 0) {
-               pid_t pid;
-
                kill(tdb_robust_mutex_pid, SIGKILL);
-
-               errno = 0;
-               pid = waitpid(tdb_robust_mutex_pid, &status, 0);
-               if (pid == tdb_robust_mutex_pid) {
-                       tdb_robust_mutex_pid = -1;
-                       break;
-               }
-               if (pid == -1 && errno != EINTR) {
-                       break;
+               ret = sigsuspend(&suspend_mask);
+               if (ret != -1 || errno != EINTR) {
+                       abort();
                }
        }
+
 cleanup_sig_child:
        tdb_robust_mutex_setup_sigchild(tdb_robust_mutext_old_handler, NULL);
+cleanup_sigmask:
+       ret = pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
+       if (ret != 0) {
+               abort();
+       }
 cleanup_m:
        pthread_mutex_destroy(m);
 cleanup_ma:


-- 
Samba Shared Repository

Reply via email to