Fix: handle sys_futex() FUTEX_WAIT interrupted by signal
[urcu.git] / urcu.c
diff --git a/urcu.c b/urcu.c
index 6f5b1e01ea04c09db4f7c5c261918750396254ea..e77306584d77f0fc012f6bfbae466452b3556b74 100644 (file)
--- a/urcu.c
+++ b/urcu.c
@@ -149,7 +149,7 @@ static void mutex_lock(pthread_mutex_t *mutex)
                        _CMM_STORE_SHARED(URCU_TLS(rcu_reader).need_mb, 0);
                        cmm_smp_mb();
                }
-               poll(NULL,0,10);
+               (void) poll(NULL, 0, 10);
        }
 #endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
 }
@@ -217,7 +217,7 @@ static void force_mb_all_readers(void)
        cds_list_for_each_entry(index, &registry, node) {
                while (CMM_LOAD_SHARED(index->need_mb)) {
                        pthread_kill(index->tid, SIGRCU);
-                       poll(NULL, 0, 1);
+                       (void) poll(NULL, 0, 1);
                }
        }
        cmm_smp_mb();   /* read ->need_mb before ending the barrier */
@@ -236,9 +236,22 @@ static void wait_gp(void)
 {
        /* Read reader_gp before read futex */
        smp_mb_master(RCU_MB_GROUP);
-       if (uatomic_read(&rcu_gp.futex) == -1)
-               futex_async(&rcu_gp.futex, FUTEX_WAIT, -1,
-                     NULL, NULL, 0);
+       if (uatomic_read(&rcu_gp.futex) != -1)
+               return;
+       while (futex_async(&rcu_gp.futex, FUTEX_WAIT, -1,
+                       NULL, NULL, 0)) {
+               switch (errno) {
+               case EWOULDBLOCK:
+                       /* Value already changed. */
+                       return;
+               case EINTR:
+                       /* Retry if interrupted by signal. */
+                       break;  /* Get out of switch. */
+               default:
+                       /* Unexpected error. */
+                       urcu_die(errno);
+               }
+       }
 }
 
 /*
This page took 0.022862 seconds and 4 git commands to generate.