I noticed that the following sequence of events would crash libvirtd when using the qemu driver: (1) establish a connection that successfully registers for domain events (either of the event-test programs will do, though the python one is currently broken -- another patch on the way for that) (2) close this connection (3) open another connection (4) do something (like start a domain) that issues a domain event The problem is that qemudClose() isn't removing registered domain event callbacks when the connection closes. This patch does that, and fixes the crash. Dave domain_event.c | 38 ++++++++++++++++++++++++++++++++++++++ domain_event.h | 3 +++ qemu_driver.c | 5 ++++- 3 files changed, 45 insertions(+), 1 deletion(-)
commit d70494a2c2ebdf985943020cc84f22713904719a Author: David Lively <dlively@xxxxxxxxxxxxxxx> Date: Thu Nov 20 16:34:32 2008 -0500 vi-patch: qemu-driver-close-fix Fix a bug in the QEMU driver causing libvirtd crashes. When closing a connection, remove the DomainEvent callbacks associated with the connection. diff --git a/src/domain_event.c b/src/domain_event.c index 85ca9b7..d5f5415 100644 --- a/src/domain_event.c +++ b/src/domain_event.c @@ -88,6 +88,44 @@ virDomainEventCallbackListRemove(virConnectPtr conn, } /** + * 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 * @cbList: the list diff --git a/src/domain_event.h b/src/domain_event.h index cfec1e1..454d084 100644 --- a/src/domain_event.h +++ b/src/domain_event.h @@ -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 diff --git a/src/qemu_driver.c b/src/qemu_driver.c index 5ad60f1..7bec116 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -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;
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list