Regular VM shutdown triggers the error for existing session of virsh console and it returns with non-zero exit code: error: internal error: console stream EOF The message and status code are misleading because there's no real error. virStreamRecv returns 0 when the end of the stream is reached. In that case, virStreamFinish should be used to get confirmation of stream completion. virSteramAbort is used otherwise to terminate the stream early before an EOF. Fixes: 29f2b5248c6 ("tools: console: pass stream/fd errors to user") Signed-off-by: Roman Bolshakov <r.bolshakov@xxxxxxxxx> --- Changes since v1: - Added needAbort parameter to virConsoleShutdown to specify if finish or abort is needed - Use it (needAbort = false) to finish stream after EOF from virStreamRecv - Print internal error if virStreamFinish or virStreamAbort do not succeed tools/virsh-console.c | 44 ++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/tools/virsh-console.c b/tools/virsh-console.c index e16f841e57..ad514a99a7 100644 --- a/tools/virsh-console.c +++ b/tools/virsh-console.c @@ -97,7 +97,7 @@ virConsoleHandleSignal(int sig ATTRIBUTE_UNUSED) static void -virConsoleShutdown(virConsolePtr con) +virConsoleShutdown(virConsolePtr con, bool needAbort) { virErrorPtr err = virGetLastError(); @@ -105,8 +105,15 @@ virConsoleShutdown(virConsolePtr con) virCopyLastError(&con->error); if (con->st) { + int termError; virStreamEventRemoveCallback(con->st); - virStreamAbort(con->st); + if (needAbort) + termError = virStreamAbort(con->st); + else + termError = virStreamFinish(con->st); + if (termError < 0) + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot terminate console stream")); virStreamFree(con->st); con->st = NULL; } @@ -158,7 +165,7 @@ virConsoleEventOnStream(virStreamPtr st, if (avail < 1024) { if (VIR_REALLOC_N(con->streamToTerminal.data, con->streamToTerminal.length + 1024) < 0) { - virConsoleShutdown(con); + virConsoleShutdown(con, true); goto cleanup; } con->streamToTerminal.length += 1024; @@ -172,11 +179,10 @@ virConsoleEventOnStream(virStreamPtr st, if (got == -2) goto cleanup; /* blocking */ if (got <= 0) { + bool needAbort = true; if (got == 0) - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("console stream EOF")); - - virConsoleShutdown(con); + needAbort = false; + virConsoleShutdown(con, needAbort); goto cleanup; } con->streamToTerminal.offset += got; @@ -195,7 +201,7 @@ virConsoleEventOnStream(virStreamPtr st, if (done == -2) goto cleanup; /* blocking */ if (done < 0) { - virConsoleShutdown(con); + virConsoleShutdown(con, true); goto cleanup; } memmove(con->terminalToStream.data, @@ -216,7 +222,7 @@ virConsoleEventOnStream(virStreamPtr st, if (events & VIR_STREAM_EVENT_ERROR || events & VIR_STREAM_EVENT_HANGUP) { - virConsoleShutdown(con); + virConsoleShutdown(con, true); } cleanup: @@ -246,7 +252,7 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED, if (avail < 1024) { if (VIR_REALLOC_N(con->terminalToStream.data, con->terminalToStream.length + 1024) < 0) { - virConsoleShutdown(con); + virConsoleShutdown(con, true); goto cleanup; } con->terminalToStream.length += 1024; @@ -260,17 +266,17 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED, if (got < 0) { if (errno != EAGAIN) { virReportSystemError(errno, "%s", _("cannot read from stdin")); - virConsoleShutdown(con); + virConsoleShutdown(con, true); } goto cleanup; } if (got == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdin")); - virConsoleShutdown(con); + virConsoleShutdown(con, true); goto cleanup; } if (con->terminalToStream.data[con->terminalToStream.offset] == con->escapeChar) { - virConsoleShutdown(con); + virConsoleShutdown(con, true); goto cleanup; } @@ -283,13 +289,13 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED, if (events & VIR_EVENT_HANDLE_ERROR) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("IO error on stdin")); - virConsoleShutdown(con); + virConsoleShutdown(con, true); goto cleanup; } if (events & VIR_EVENT_HANDLE_HANGUP) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdin")); - virConsoleShutdown(con); + virConsoleShutdown(con, true); goto cleanup; } @@ -322,7 +328,7 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED, if (done < 0) { if (errno != EAGAIN) { virReportSystemError(errno, "%s", _("cannot write to stdout")); - virConsoleShutdown(con); + virConsoleShutdown(con, true); } goto cleanup; } @@ -344,13 +350,13 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED, if (events & VIR_EVENT_HANDLE_ERROR) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("IO error stdout")); - virConsoleShutdown(con); + virConsoleShutdown(con, true); goto cleanup; } if (events & VIR_EVENT_HANDLE_HANGUP) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdout")); - virConsoleShutdown(con); + virConsoleShutdown(con, true); goto cleanup; } @@ -489,7 +495,7 @@ virshRunConsole(vshControl *ctl, ret = 0; cleanup: - virConsoleShutdown(con); + virConsoleShutdown(con, true); if (ret < 0) { vshResetLibvirtError(); -- 2.22.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list