]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Fix crash due to failure to unregister event callbacks in QEMU driver (David Lively)
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 21 Nov 2008 10:17:22 +0000 (10:17 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 21 Nov 2008 10:17:22 +0000 (10:17 +0000)
ChangeLog
src/domain_event.c
src/domain_event.h
src/qemu_driver.c

index 093b3785ce67b81ca667c86a25a39b467f18cfe8..0fa64ddb85d46e0f43c92c7966a26d7208c3e858 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Fri Nov 21 10:14:14 BST 2008 Daniel P. Berrange <berrange@redhat.com>
+
+       Fix crash due to failure to unregister event callbacks on
+       connection close (David Lively)
+       * src/domain_event.c, src/domain_event.h: Helper for unregistering
+       all callbacks
+       * src/qemu_driver.c: Unregister all callbacks on connection close
+
 Fri Nov 21 10:10:14 BST 2008 Daniel P. Berrange <berrange@redhat.com>
 
        * src/Makefile.am: Include Xen compile flags for libvirt_driver.la
index 85ca9b7bd27194dd0707bd37d523c303eb0f0df9..d5f54158c60522a1b11e6f74f4925310b23a730a 100644 (file)
@@ -87,6 +87,44 @@ virDomainEventCallbackListRemove(virConnectPtr conn,
     return -1;
 }
 
+/**
+ * virDomainEventCallbackListRemoveConn:
+ * @conn: pointer to the connection
+ * @cbList: the list
+ *
+ * Internal function to remove all of a given connection's callback
+ * from a virDomainEventCallbackListPtr
+ */
+int
+virDomainEventCallbackListRemoveConn(virConnectPtr conn,
+                                     virDomainEventCallbackListPtr cbList)
+{
+    int old_count = cbList->count;
+    int i;
+    for (i = 0 ; i < cbList->count ; i++) {
+        if(cbList->callbacks[i]->conn == conn) {
+            virFreeCallback freecb = cbList->callbacks[i]->freecb;
+            if (freecb)
+                (*freecb)(cbList->callbacks[i]->opaque);
+            virUnrefConnect(cbList->callbacks[i]->conn);
+            VIR_FREE(cbList->callbacks[i]);
+
+            if (i < (cbList->count - 1))
+                memmove(cbList->callbacks + i,
+                        cbList->callbacks + i + 1,
+                        sizeof(*(cbList->callbacks)) *
+                                (cbList->count - (i + 1)));
+            cbList->count--;
+            i--;
+        }
+    }
+    if (cbList->count < old_count &&
+        VIR_REALLOC_N(cbList->callbacks, cbList->count) < 0) {
+        ; /* Failure to reduce memory allocation isn't fatal */
+    }
+    return 0;
+}
+
 /**
  * virDomainEventCallbackListAdd:
  * @conn: pointer to the connection
index cfec1e16cbc89bc5116b99f914b7b55a53eb96da..32ae0dbc4798b5e10de15b803a2d663e05219fbd 100644 (file)
@@ -55,6 +55,9 @@ int virDomainEventCallbackListRemove(virConnectPtr conn,
                                      virDomainEventCallbackListPtr cbList,
                                      virConnectDomainEventCallback callback);
 
+int virDomainEventCallbackListRemoveConn(virConnectPtr conn,
+                                         virDomainEventCallbackListPtr cbList);
+
 /**
  * Dispatching domain events that come in while
  * in a call / response rpc
index 5ad60f1dd2ed293412528145c739461e8df11a50..7bec116bdcb7869ce8af276cbfbafd861217d201 100644 (file)
@@ -1235,7 +1235,10 @@ static virDrvOpenStatus qemudOpen(virConnectPtr conn,
 }
 
 static int qemudClose(virConnectPtr conn) {
-    /*struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;*/
+    struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
+
+    /* Get rid of callbacks registered for this conn */
+    virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks);
 
     conn->privateData = NULL;