mirror of https://gitee.com/openkylin/libvirt.git
Fix reference counting bug in virsh console
The event watches need to be removed before the event loop terminates, otherwise they cause a dangling reference to be held on the virStreamPtr, which in turns holds a reference on virConnectPtr, which in turn causes errors like "Failed to disconnect from the hypervisor" * tools/console.c: Remove watches before event loop quits * tools/virsh.c: Print out dangling reference count
This commit is contained in:
parent
5fb9db272d
commit
a926156792
|
@ -88,6 +88,19 @@ cfmakeraw (struct termios *attr)
|
||||||
}
|
}
|
||||||
# endif /* !HAVE_CFMAKERAW */
|
# endif /* !HAVE_CFMAKERAW */
|
||||||
|
|
||||||
|
static void
|
||||||
|
virConsoleShutdown(virConsolePtr con)
|
||||||
|
{
|
||||||
|
con->quit = true;
|
||||||
|
virStreamEventRemoveCallback(con->st);
|
||||||
|
if (con->stdinWatch != -1)
|
||||||
|
virEventRemoveHandleImpl(con->stdinWatch);
|
||||||
|
if (con->stdinWatch != -1)
|
||||||
|
virEventRemoveHandleImpl(con->stdoutWatch);
|
||||||
|
con->stdinWatch = -1;
|
||||||
|
con->stdoutWatch = -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
virConsoleEventOnStream(virStreamPtr st,
|
virConsoleEventOnStream(virStreamPtr st,
|
||||||
int events, void *opaque)
|
int events, void *opaque)
|
||||||
|
@ -103,7 +116,7 @@ virConsoleEventOnStream(virStreamPtr st,
|
||||||
if (VIR_REALLOC_N(con->streamToTerminal.data,
|
if (VIR_REALLOC_N(con->streamToTerminal.data,
|
||||||
con->streamToTerminal.length + 1024) < 0) {
|
con->streamToTerminal.length + 1024) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
con->streamToTerminal.length += 1024;
|
con->streamToTerminal.length += 1024;
|
||||||
|
@ -117,7 +130,7 @@ virConsoleEventOnStream(virStreamPtr st,
|
||||||
if (got == -2)
|
if (got == -2)
|
||||||
return; /* blocking */
|
return; /* blocking */
|
||||||
if (got <= 0) {
|
if (got <= 0) {
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
con->streamToTerminal.offset += got;
|
con->streamToTerminal.offset += got;
|
||||||
|
@ -136,7 +149,7 @@ virConsoleEventOnStream(virStreamPtr st,
|
||||||
if (done == -2)
|
if (done == -2)
|
||||||
return; /* blocking */
|
return; /* blocking */
|
||||||
if (done < 0) {
|
if (done < 0) {
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memmove(con->terminalToStream.data,
|
memmove(con->terminalToStream.data,
|
||||||
|
@ -158,7 +171,7 @@ virConsoleEventOnStream(virStreamPtr st,
|
||||||
|
|
||||||
if (events & VIR_STREAM_EVENT_ERROR ||
|
if (events & VIR_STREAM_EVENT_ERROR ||
|
||||||
events & VIR_STREAM_EVENT_HANGUP) {
|
events & VIR_STREAM_EVENT_HANGUP) {
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +192,7 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED,
|
||||||
if (VIR_REALLOC_N(con->terminalToStream.data,
|
if (VIR_REALLOC_N(con->terminalToStream.data,
|
||||||
con->terminalToStream.length + 1024) < 0) {
|
con->terminalToStream.length + 1024) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
con->terminalToStream.length += 1024;
|
con->terminalToStream.length += 1024;
|
||||||
|
@ -192,16 +205,16 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED,
|
||||||
avail);
|
avail);
|
||||||
if (got < 0) {
|
if (got < 0) {
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (got == 0) {
|
if (got == 0) {
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (con->terminalToStream.data[con->terminalToStream.offset] == CTRL_CLOSE_BRACKET) {
|
if (con->terminalToStream.data[con->terminalToStream.offset] == CTRL_CLOSE_BRACKET) {
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +227,7 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED,
|
||||||
|
|
||||||
if (events & VIR_EVENT_HANDLE_ERROR ||
|
if (events & VIR_EVENT_HANDLE_ERROR ||
|
||||||
events & VIR_EVENT_HANDLE_HANGUP) {
|
events & VIR_EVENT_HANDLE_HANGUP) {
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +248,7 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED,
|
||||||
con->streamToTerminal.offset);
|
con->streamToTerminal.offset);
|
||||||
if (done < 0) {
|
if (done < 0) {
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +271,7 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED,
|
||||||
|
|
||||||
if (events & VIR_EVENT_HANDLE_ERROR ||
|
if (events & VIR_EVENT_HANDLE_ERROR ||
|
||||||
events & VIR_EVENT_HANDLE_HANGUP) {
|
events & VIR_EVENT_HANDLE_HANGUP) {
|
||||||
con->quit = true;
|
virConsoleShutdown(con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,10 +354,6 @@ int vshRunConsole(virDomainPtr dom, const char *devname)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
virStreamEventRemoveCallback(con->st);
|
|
||||||
virEventRemoveHandleImpl(con->stdinWatch);
|
|
||||||
virEventRemoveHandleImpl(con->stdoutWatch);
|
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
|
@ -637,8 +637,9 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd)
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (ctl->conn) {
|
if (ctl->conn) {
|
||||||
if (virConnectClose(ctl->conn) != 0) {
|
int ret;
|
||||||
vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
|
if ((ret = virConnectClose(ctl->conn)) != 0) {
|
||||||
|
vshError(ctl, _("Failed to disconnect from the hypervisor, %d leaked reference(s)"), ret);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
ctl->conn = NULL;
|
ctl->conn = NULL;
|
||||||
|
@ -11463,8 +11464,9 @@ vshDeinit(vshControl *ctl)
|
||||||
vshCloseLogFile(ctl);
|
vshCloseLogFile(ctl);
|
||||||
VIR_FREE(ctl->name);
|
VIR_FREE(ctl->name);
|
||||||
if (ctl->conn) {
|
if (ctl->conn) {
|
||||||
if (virConnectClose(ctl->conn) != 0) {
|
int ret;
|
||||||
vshError(ctl, "%s", _("failed to disconnect from the hypervisor"));
|
if ((ret = virConnectClose(ctl->conn)) != 0) {
|
||||||
|
vshError(ctl, _("Failed to disconnect from the hypervisor, %d leaked reference(s)"), ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virResetLastError();
|
virResetLastError();
|
||||||
|
|
Loading…
Reference in New Issue