From 7cea74a3b2dee6a4b735d7877de47f0ecd86fb77 Mon Sep 17 00:00:00 2001 From: Erik Skultety Date: Thu, 10 Nov 2016 13:20:26 +0100 Subject: [PATCH] datatypes: Introduce some admin-related close callback handling helpers Well, there were three different spots where closeCallback->freeCallback was called, not looking the same --> potential for bugs - and there indeed is a bug with refcounting of the @conn object. So this patch partially follows the path set by commit 24dbb69f by introducing some close callback helpers both to replace all the spots where we call clean the close callback data with a dedicated function and to be able to fix the refcounting bug causing a memleak. Signed-off-by: Erik Skultety --- po/POTFILES.in | 1 + src/datatypes.c | 62 ++++++++++++++++++++++++++++++++++ src/datatypes.h | 8 +++++ src/libvirt_admin_private.syms | 3 ++ 4 files changed, 74 insertions(+) diff --git a/po/POTFILES.in b/po/POTFILES.in index 1469240221..5a370833a9 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -47,6 +47,7 @@ src/cpu/cpu_arm.c src/cpu/cpu_map.c src/cpu/cpu_ppc64.c src/cpu/cpu_x86.c +src/datatypes.c src/driver.c src/esx/esx_driver.c src/esx/esx_network_driver.c diff --git a/src/datatypes.c b/src/datatypes.c index ff0c46fab0..24e4f776a0 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -935,6 +935,68 @@ virAdmConnectCloseCallbackDataDispose(void *obj) virObjectUnlock(cb_data); } +void +virAdmConnectCloseCallbackDataReset(virAdmConnectCloseCallbackDataPtr cbdata) +{ + if (cbdata->freeCallback) + cbdata->freeCallback(cbdata->opaque); + + virObjectUnref(cbdata->conn); + cbdata->conn = NULL; + cbdata->freeCallback = NULL; + cbdata->callback = NULL; + cbdata->opaque = NULL; +} + +int +virAdmConnectCloseCallbackDataUnregister(virAdmConnectCloseCallbackDataPtr cbdata, + virAdmConnectCloseFunc cb) +{ + int ret = -1; + + virObjectLock(cbdata); + if (cbdata->callback != cb) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("A different callback was requested")); + goto cleanup; + } + + virAdmConnectCloseCallbackDataReset(cbdata); + ret = 0; + cleanup: + virObjectUnlock(cbdata); + return ret; +} + +int +virAdmConnectCloseCallbackDataRegister(virAdmConnectCloseCallbackDataPtr cbdata, + virAdmConnectPtr conn, + virAdmConnectCloseFunc cb, + void *opaque, + virFreeCallback freecb) +{ + int ret = -1; + + virObjectLock(cbdata); + + if (cbdata->callback) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("A close callback is already registered")); + goto cleanup; + } + + virObjectRef(conn); + cbdata->conn = conn; + cbdata->callback = cb; + cbdata->opaque = opaque; + cbdata->freeCallback = freecb; + + ret = 0; + cleanup: + virObjectUnlock(conn->closeCallback); + return ret; +} + virAdmServerPtr virAdmGetServer(virAdmConnectPtr conn, const char *name) { diff --git a/src/datatypes.h b/src/datatypes.h index 2b6adb4c45..9a5fbbc2a0 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -722,5 +722,13 @@ void virConnectCloseCallbackDataCall(virConnectCloseCallbackDataPtr close, int reason); virConnectCloseFunc virConnectCloseCallbackDataGetCallback(virConnectCloseCallbackDataPtr close); +void virAdmConnectCloseCallbackDataReset(virAdmConnectCloseCallbackDataPtr cbdata); +int virAdmConnectCloseCallbackDataRegister(virAdmConnectCloseCallbackDataPtr cbdata, + virAdmConnectPtr conn, + virAdmConnectCloseFunc cb, + void *opaque, + virFreeCallback freecb); +int virAdmConnectCloseCallbackDataUnregister(virAdmConnectCloseCallbackDataPtr cbdata, + virAdmConnectCloseFunc cb); #endif /* __VIR_DATATYPES_H__ */ diff --git a/src/libvirt_admin_private.syms b/src/libvirt_admin_private.syms index 8c173ab428..191e3f2ef8 100644 --- a/src/libvirt_admin_private.syms +++ b/src/libvirt_admin_private.syms @@ -29,6 +29,9 @@ xdr_admin_server_set_threadpool_parameters_args; # datatypes.h virAdmClientClass; virAdmConnectClass; +virAdmConnectCloseCallbackDataRegister; +virAdmConnectCloseCallbackDataReset; +virAdmConnectCloseCallbackDataUnregister; virAdmGetServer; virAdmServerClass;