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 <eskultet@redhat.com>
This commit is contained in:
Erik Skultety 2016-11-10 13:20:26 +01:00
parent d46a1e5d45
commit 7cea74a3b2
4 changed files with 74 additions and 0 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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__ */

View File

@ -29,6 +29,9 @@ xdr_admin_server_set_threadpool_parameters_args;
# datatypes.h
virAdmClientClass;
virAdmConnectClass;
virAdmConnectCloseCallbackDataRegister;
virAdmConnectCloseCallbackDataReset;
virAdmConnectCloseCallbackDataUnregister;
virAdmGetServer;
virAdmServerClass;