Before closing the connection we unregister the close callback
to prevent a reference leak. We make sure that we only unregister
if we have previously registered a callback (not the case for
virsh connect!). Further, the messages on virConnectClose != 0
are a bit more specific now.
Signed-off-by: Viktor Mihajlovski <mihajlov(a)linux.vnet.ibm.com>
---
tools/virsh.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index d822e09..4be8fa0 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -311,6 +311,8 @@ vshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED,
disconnected++;
}
+static int callback_registered = 0;
+
/*
* vshReconnect:
*
@@ -336,9 +338,13 @@ vshReconnect(vshControl *ctl)
else
vshError(ctl, "%s", _("failed to connect to the
hypervisor"));
} else {
- if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect,
- NULL, NULL) < 0)
- vshError(ctl, "%s", _("Unable to register disconnect
callback"));
+ if (!callback_registered) {
+ if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect,
+ NULL, NULL) == 0)
+ callback_registered = 1;
+ else
+ vshError(ctl, "%s", _("Unable to register disconnect
callback"));
+ }
if (connected)
vshError(ctl, "%s", _("Reconnected to the hypervisor"));
}
@@ -2672,9 +2678,14 @@ vshDeinit(vshControl *ctl)
VIR_FREE(ctl->name);
if (ctl->conn) {
int ret;
- if ((ret = virConnectClose(ctl->conn)) != 0) {
- vshError(ctl, _("Failed to disconnect from the hypervisor, %d leaked
reference(s)"), ret);
- }
+ if (callback_registered &&
+ virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect) < 0)
+ vshError(ctl, "%s", _("Failed to unregister disconnect
callback"));
+ ret = virConnectClose(ctl->conn);
+ if (ret < 0)
+ vshError(ctl, "%s", _("Failed to disconnect from the
hypervisor"));
+ else if (ret > 0)
+ vshError(ctl, "%s", _("Leaked reference(s) after disconnect
from the hypervisor"));
}
virResetLastError();
--
1.7.9.5