static void
-virConsoleShutdown(virConsolePtr con)
+virConsoleShutdown(virConsolePtr con,
+ bool graceful)
{
virErrorPtr err = virGetLastError();
virCopyLastError(&con->error);
if (con->st) {
+ int rc;
+
virStreamEventRemoveCallback(con->st);
- if (virStreamAbort(con->st) < 0)
+ if (graceful)
+ rc = virStreamFinish(con->st);
+ else
+ rc = virStreamAbort(con->st);
+
+ if (rc < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot terminate console stream"));
+ }
virStreamFree(con->st);
con->st = NULL;
}
if (avail < 1024) {
if (VIR_REALLOC_N(con->streamToTerminal.data,
con->streamToTerminal.length + 1024) < 0) {
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
goto cleanup;
}
con->streamToTerminal.length += 1024;
if (got == -2)
goto cleanup; /* blocking */
if (got <= 0) {
- virConsoleShutdown(con);
+ virConsoleShutdown(con, got == 0);
goto cleanup;
}
con->streamToTerminal.offset += got;
if (done == -2)
goto cleanup; /* blocking */
if (done < 0) {
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
goto cleanup;
}
memmove(con->terminalToStream.data,
if (events & VIR_STREAM_EVENT_ERROR ||
events & VIR_STREAM_EVENT_HANGUP) {
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
}
cleanup:
if (avail < 1024) {
if (VIR_REALLOC_N(con->terminalToStream.data,
con->terminalToStream.length + 1024) < 0) {
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
goto cleanup;
}
con->terminalToStream.length += 1024;
if (got < 0) {
if (errno != EAGAIN) {
virReportSystemError(errno, "%s", _("cannot read from stdin"));
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
}
goto cleanup;
}
if (got == 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdin"));
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
goto cleanup;
}
if (con->terminalToStream.data[con->terminalToStream.offset] == con->escapeChar) {
- virConsoleShutdown(con);
+ virConsoleShutdown(con, true);
goto cleanup;
}
if (events & VIR_EVENT_HANDLE_ERROR) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("IO error on stdin"));
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
goto cleanup;
}
if (events & VIR_EVENT_HANDLE_HANGUP) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdin"));
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
goto cleanup;
}
if (done < 0) {
if (errno != EAGAIN) {
virReportSystemError(errno, "%s", _("cannot write to stdout"));
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
}
goto cleanup;
}
if (events & VIR_EVENT_HANDLE_ERROR) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("IO error stdout"));
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
goto cleanup;
}
if (events & VIR_EVENT_HANDLE_HANGUP) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdout"));
- virConsoleShutdown(con);
+ virConsoleShutdown(con, false);
goto cleanup;
}
ret = 0;
cleanup:
- virConsoleShutdown(con);
+ virConsoleShutdown(con, ret == 0);
if (ret < 0) {
vshResetLibvirtError();