[libvirt] [PATCH 2/2] tools: console: pass stream/fd errors to user
Nikolay Shirokovskiy
nshirokovskiy at virtuozzo.com
Mon Feb 25 13:02:01 UTC 2019
On 22.02.2019 18:07, John Ferlan wrote:
>
>
> On 2/15/19 9:39 AM, Nikolay Shirokovskiy wrote:
>> If console disconnected due to connection problem or problem on server
>
> If the console was disconnected due to a connection problem or a problem
> on the server
>
>> side for example it is convinient to provide the cause to the user.
>
> side it is convenient
>
>> If error comes from API then error is saved in virsh global variable
>
> If the error come from the API, then the error is save in a virsh global
> variable.
>
>> but as we return success from virshRunConsole if we reach waiting
>
> However, since success is returned from virshRunConsole and we reach the
> waiting
>
>> stage then error is never reported. Let's track for error in event loop!
>
> stage, then the error is never reported. Let's track the error in the
> event loop.
>>
>> Next after failure we do a cleanup and this cleanup can overwrite
>> root cause. Let's save root cause and then set it to virsh error
>> after all cleanup is done.
>
> [I think this paragraph could be dropped in favor of below]
I would like to keep it. It explains next construction in patch.
+
+ if (ret < 0) {
+ vshResetLibvirtError();
+ virSetError(&con->error);
+ vshSaveLibvirtHelperError();
+ }
+
Nikolay
>
>>
>> Let's also add missing error reports in code.
>
> Written this way it feels like an extra patch; however, I know it's
> not... How about...
>
> Since we'll be sending the error to the consumer, each failure path from
> the event handlers needs to be augmented to provide what error generated
> the failure so that can be reported properly during cleanup processing
> from virshRunConsole.
>
>
>>
>> Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
>> ---
>> tools/virsh-console.c | 59 +++++++++++++++++++++++++++++++++++++++++++--------
>> 1 file changed, 50 insertions(+), 9 deletions(-)
>>
>> diff --git a/tools/virsh-console.c b/tools/virsh-console.c
>> index c0c3f90..f1ad076 100644
>> --- a/tools/virsh-console.c
>> +++ b/tools/virsh-console.c
>> @@ -73,6 +73,7 @@ struct virConsole {
>> struct virConsoleBuffer terminalToStream;
>>
>> char escapeChar;
>> + virError error;
>> };
>>
>> static virClassPtr virConsoleClass;
>> @@ -98,6 +99,11 @@ virConsoleHandleSignal(int sig ATTRIBUTE_UNUSED)
>> static void
>> virConsoleShutdown(virConsolePtr con)
>> {
>> + virErrorPtr err = virGetLastError();
>> +
>> + if (con->error.code == VIR_ERR_OK && err && err->code != VIR_ERR_OK)
>> + virCopyLastError(&con->error);
>> +
>> if (con->st) {
>> virStreamEventRemoveCallback(con->st);
>> virStreamAbort(con->st);
>> @@ -126,6 +132,7 @@ virConsoleDispose(void *obj)
>> virStreamFree(con->st);
>>
>> virCondDestroy(&con->cond);
>> + virResetError(&con->error);
>> }
>>
>>
>> @@ -162,7 +169,13 @@ virConsoleEventOnStream(virStreamPtr st,
>> avail);
>> if (got == -2)
>> goto cleanup; /* blocking */
>> - if (got <= 0) {
>> + if (got == 0) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("console stream EOF"));
>> + virConsoleShutdown(con);
>> + goto cleanup;
>> + }
>> + if (got < 0) {
>
> if (got <= 0) {
> if (got == 0)
> virReportError(...)
> virConsoleShutdown
> goto cleanup
> }
>
>> virConsoleShutdown(con);
>> goto cleanup;
>> }
>> @@ -245,11 +258,14 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED,
>> con->terminalToStream.offset,
>> avail);
>> if (got < 0) {
>> - if (errno != EAGAIN)
>> + if (errno != EAGAIN) {
>> + virReportSystemError(errno, "%s", _("can not read from stdin"));
>
> "cannot" is fine (similar below)
>
> John
>
>> virConsoleShutdown(con);
>> + }
>> goto cleanup;
>> }
>> if (got == 0) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdin"));
>> virConsoleShutdown(con);
>> goto cleanup;
>> }
>> @@ -265,9 +281,16 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED,
>> VIR_STREAM_EVENT_WRITABLE);
>> }
>>
>> - if (events & VIR_EVENT_HANDLE_ERROR ||
>> - events & VIR_EVENT_HANDLE_HANGUP) {
>> + if (events & VIR_EVENT_HANDLE_ERROR) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("IO error on stdin"));
>> virConsoleShutdown(con);
>> + goto cleanup;
>> + }
>> +
>> + if (events & VIR_EVENT_HANDLE_HANGUP) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdin"));
>> + virConsoleShutdown(con);
>> + goto cleanup;
>> }
>>
>> cleanup:
>> @@ -297,8 +320,10 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED,
>> con->streamToTerminal.data,
>> con->streamToTerminal.offset);
>> if (done < 0) {
>> - if (errno != EAGAIN)
>> + if (errno != EAGAIN) {
>> + virReportSystemError(errno, "%s", _("can not write to stdout"));
>> virConsoleShutdown(con);
>> + }
>> goto cleanup;
>> }
>> memmove(con->streamToTerminal.data,
>> @@ -317,9 +342,16 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED,
>> if (!con->streamToTerminal.offset)
>> virEventUpdateHandle(con->stdoutWatch, 0);
>>
>> - if (events & VIR_EVENT_HANDLE_ERROR ||
>> - events & VIR_EVENT_HANDLE_HANGUP) {
>> + if (events & VIR_EVENT_HANDLE_ERROR) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("IO error stdout"));
>> virConsoleShutdown(con);
>> + goto cleanup;
>> + }
>> +
>> + if (events & VIR_EVENT_HANDLE_HANGUP) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdout"));
>> + virConsoleShutdown(con);
>> + goto cleanup;
>> }
>>
>> cleanup:
>> @@ -447,15 +479,24 @@ virshRunConsole(vshControl *ctl,
>>
>> while (!con->quit) {
>> if (virCondWait(&con->cond, &con->parent.lock) < 0) {
>> - VIR_ERROR(_("unable to wait on console condition"));
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("unable to wait on console condition"));
>> goto cleanup;
>> }
>> }
>>
>> - ret = 0;
>> + if (con->error.code == VIR_ERR_OK)
>> + ret = 0;
>>
>> cleanup:
>> virConsoleShutdown(con);
>> +
>> + if (ret < 0) {
>> + vshResetLibvirtError();
>> + virSetError(&con->error);
>> + vshSaveLibvirtHelperError();
>> + }
>> +
>> virObjectUnlock(con);
>> virObjectUnref(con);
>>
>>
More information about the libvir-list
mailing list