]> xenbits.xensource.com Git - libvirt.git/commitdiff
tests: fix deadlock in eventtest
authorPavel Hrdina <phrdina@redhat.com>
Thu, 6 Feb 2020 12:00:25 +0000 (13:00 +0100)
committerPavel Hrdina <phrdina@redhat.com>
Thu, 6 Feb 2020 12:41:03 +0000 (13:41 +0100)
There is a race deadlock in eventtest after the recent rewrite to drop
GNULIB from libvirt code base.

The issue happens when the callbacks testPipeReader() or testTimer()
are called before waitEvents() starts waiting on `eventThreadCond`.
It will never happen because the callbacks are already done and there
is nothing that will signal the condition again.

Reported-by: Peter Krempa <pkrempa@redhat.com>
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
tests/eventtest.c

index 9855b578fbf0166c6256bd043d4cc8ef0ed761a2..06b5e7b20c48a19cf2b47fe05dee5b75e3647ceb 100644 (file)
@@ -43,6 +43,7 @@ VIR_LOG_INIT("tests.eventtest");
 
 static pthread_mutex_t eventThreadMutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t eventThreadCond = PTHREAD_COND_INITIALIZER;
+static bool eventThreadSignaled;
 
 static struct handleInfo {
     int pipeFD[2];
@@ -138,8 +139,9 @@ testPipeReader(int watch, int fd, int events, void *data)
         virEventRemoveHandle(info->delete);
 
  cleanup:
-    pthread_mutex_unlock(&eventThreadMutex);
     pthread_cond_signal(&eventThreadCond);
+    eventThreadSignaled = true;
+    pthread_mutex_unlock(&eventThreadMutex);
 }
 
 
@@ -164,8 +166,9 @@ testTimer(int timer, void *data)
         virEventRemoveTimeout(info->delete);
 
  cleanup:
-    pthread_mutex_unlock(&eventThreadMutex);
     pthread_cond_signal(&eventThreadCond);
+    eventThreadSignaled = true;
+    pthread_mutex_unlock(&eventThreadMutex);
 }
 
 G_GNUC_NORETURN static void *eventThreadLoop(void *data G_GNUC_UNUSED) {
@@ -185,7 +188,10 @@ waitEvents(int nhandle, int ntimer)
     VIR_DEBUG("Wait events nhandle %d ntimer %d",
               nhandle, ntimer);
     while (ngothandle != nhandle || ngottimer != ntimer) {
-        pthread_cond_wait(&eventThreadCond, &eventThreadMutex);
+        while (!eventThreadSignaled)
+            pthread_cond_wait(&eventThreadCond, &eventThreadMutex);
+
+        eventThreadSignaled = false;
 
         ngothandle = ngottimer = 0;
         for (i = 0; i < NUM_FDS; i++) {