Fix: handle sys_futex() FUTEX_WAIT interrupted by signal
[urcu.git] / urcu-defer-impl.h
index a7d0b2f7c45aa0a1054d70aac989293b63c87466..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);
+                       }
+               }
        }
 }
 
@@ -300,7 +314,7 @@ end:
 /*
  * _defer_rcu - Queue a RCU callback.
  */
-void _defer_rcu(void (*fct)(void *p), void *p)
+static void _defer_rcu(void (*fct)(void *p), void *p)
 {
        unsigned long head, tail;
 
@@ -363,7 +377,7 @@ void _defer_rcu(void (*fct)(void *p), void *p)
        wake_up_defer();
 }
 
-void *thr_defer(void *args)
+static void *thr_defer(void *args)
 {
        for (;;) {
                /*
@@ -373,7 +387,7 @@ 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.023521 seconds and 4 git commands to generate.