VCL: Fix race condition in event thread function 30/11130/1
authorDave Wallace <dwallacelf@gmail.com>
Tue, 13 Mar 2018 23:42:02 +0000 (19:42 -0400)
committerDave Wallace <dwallacelf@gmail.com>
Tue, 13 Mar 2018 23:42:02 +0000 (19:42 -0400)
Change-Id: I8586faee0b3a40932cd711b60cebe1a23ff82a56
Signed-off-by: Dave Wallace <dwallacelf@gmail.com>
src/vcl/vcl_event.c

index f6e20de..d8bd8c7 100644 (file)
@@ -211,16 +211,19 @@ vce_event_thread_fn (void *arg)
   vce_event_handler_reg_t *handler;
   uword *p;
 
+  pthread_mutex_lock (&(evt->generator_lock));
+  clib_spinlock_lock (&(evt->events_lockp));
   evt->recycle_event = 1; // Used for recycling events with no handlers
-
+  clib_spinlock_unlock (&(evt->events_lockp));
 
   do
     {
-      pthread_mutex_lock (&(evt->generator_lock));
       while ( (clib_fifo_elts (evt->event_index_fifo) == 0) ||
              evt->recycle_event)
        {
+          clib_spinlock_lock (&(evt->events_lockp));
          evt->recycle_event = 0;
+          clib_spinlock_unlock (&(evt->events_lockp));
          pthread_cond_wait (&(evt->generator_cond),
                             &(evt->generator_lock));
        }
@@ -231,8 +234,6 @@ vce_event_thread_fn (void *arg)
       clib_fifo_sub1 (evt->event_index_fifo, ev_idx);
       ev = pool_elt_at_index (evt->vce_events, ev_idx);
 
-      clib_spinlock_unlock (&(evt->events_lockp));
-
       ASSERT(ev);
 
       clib_spinlock_lock (&evt->handlers_lockp);
@@ -245,18 +246,23 @@ vce_event_thread_fn (void *arg)
           * I don't know either, so lets try recycling the event */
          clib_fifo_add1 (evt->event_index_fifo, ev_idx);
          evt->recycle_event = 1;
+          clib_spinlock_unlock (&(evt->events_lockp));
          clib_spinlock_unlock (&evt->handlers_lockp);
-         goto unlock;
+          pthread_mutex_unlock (&(evt->generator_lock));
        }
-      handler = pool_elt_at_index (evt->vce_event_handlers, p[0]);
-      handler->ev_idx = ev_idx;
+      else
+        {
+          handler = pool_elt_at_index (evt->vce_event_handlers, p[0]);
+          handler->ev_idx = ev_idx;
 
-      clib_spinlock_unlock (&evt->handlers_lockp);
+          clib_spinlock_unlock (&(evt->events_lockp));
+          clib_spinlock_unlock (&evt->handlers_lockp);
+          pthread_mutex_unlock (&(evt->generator_lock));
 
-      (handler->handler_fn)(handler);
+          (handler->handler_fn)(handler);
+        }
 
-    unlock:
-      pthread_mutex_unlock (&(evt->generator_lock));
+      pthread_mutex_lock (&(evt->generator_lock));
     }
   while (1);
   return NULL;