Fix: handle sys_futex() FUTEX_WAIT interrupted by signal
[urcu.git] / urcu-defer-impl.h
index c762400574cdea19947f0fd265d8c2a4fbb81f6e..f1dca8ff85c2289d300cc92a77e9d623cbb39216 100644 (file)
@@ -148,7 +148,7 @@ static void mutex_lock_defer(pthread_mutex_t *mutex)
        while ((ret = pthread_mutex_trylock(mutex)) != 0) {
                if (ret != EBUSY && ret != EINTR)
                        urcu_die(ret);
-               poll(NULL,0,10);
+               (void) poll(NULL,0,10);
        }
 #endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
 }
@@ -160,8 +160,9 @@ static void wake_up_defer(void)
 {
        if (caa_unlikely(uatomic_read(&defer_thread_futex) == -1)) {
                uatomic_set(&defer_thread_futex, 0);
-               futex_noasync(&defer_thread_futex, FUTEX_WAKE, 1,
-                     NULL, NULL, 0);
+               if (futex_noasync(&defer_thread_futex, FUTEX_WAKE, 1,
+                               NULL, NULL, 0) < 0)
+                       urcu_die(errno);
        }
 }
 
@@ -198,9 +199,22 @@ static void wait_defer(void)
                uatomic_set(&defer_thread_futex, 0);
        } else {
                cmm_smp_rmb();  /* Read queue before read futex */
-               if (uatomic_read(&defer_thread_futex) == -1)
-                       futex_noasync(&defer_thread_futex, FUTEX_WAIT, -1,
-                             NULL, NULL, 0);
+               if (uatomic_read(&defer_thread_futex) != -1)
+                       return;
+               while (futex_noasync(&defer_thread_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);
+                       }
+               }
        }
 }
 
@@ -373,7 +387,7 @@ static void *thr_defer(void *args)
                 */
                wait_defer();
                /* Sleeping after wait_defer to let many callbacks enqueue */
-               poll(NULL,0,100);       /* wait for 100ms */
+               (void) poll(NULL,0,100);        /* wait for 100ms */
                rcu_defer_barrier();
        }
 
This page took 0.027178 seconds and 4 git commands to generate.