From nobody Sat May 4 03:51:35 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1550241659951519.448697942652; Fri, 15 Feb 2019 06:40:59 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B0AC2C059B87; Fri, 15 Feb 2019 14:40:57 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7EF4B5DF28; Fri, 15 Feb 2019 14:40:57 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 20CDA181A00D; Fri, 15 Feb 2019 14:40:57 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x1FEep12003103 for ; Fri, 15 Feb 2019 09:40:51 -0500 Received: by smtp.corp.redhat.com (Postfix) id 38C1026FD5; Fri, 15 Feb 2019 14:40:51 +0000 (UTC) Received: from mx1.redhat.com (ext-mx09.extmail.prod.ext.phx2.redhat.com [10.5.110.38]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 306B926FD3 for ; Fri, 15 Feb 2019 14:40:45 +0000 (UTC) Received: from relay.sw.ru (relay.sw.ru [185.231.240.75]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4319F124565 for ; Fri, 15 Feb 2019 14:40:44 +0000 (UTC) Received: from [10.94.3.220] (helo=dim-vz7.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1guefS-0005Db-Ky for libvir-list@redhat.com; Fri, 15 Feb 2019 17:40:42 +0300 From: Nikolay Shirokovskiy To: libvir-list@redhat.com Date: Fri, 15 Feb 2019 17:39:34 +0300 Message-Id: <1550241575-871081-2-git-send-email-nshirokovskiy@virtuozzo.com> In-Reply-To: <1550241575-871081-1-git-send-email-nshirokovskiy@virtuozzo.com> References: <1550241575-871081-1-git-send-email-nshirokovskiy@virtuozzo.com> X-Greylist: Sender passed SPF test, ACL 242 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 15 Feb 2019 14:40:44 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 15 Feb 2019 14:40:44 +0000 (UTC) for IP:'185.231.240.75' DOMAIN:'relay.sw.ru' HELO:'relay.sw.ru' FROM:'nshirokovskiy@virtuozzo.com' RCPT:'' X-RedHat-Spam-Score: -0.001 (SPF_PASS) 185.231.240.75 relay.sw.ru 185.231.240.75 relay.sw.ru X-Scanned-By: MIMEDefang 2.78 on 10.5.110.38 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 1/2] tools: console: cleanup console on errors in main thread X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Fri, 15 Feb 2019 14:40:58 +0000 (UTC) Content-Type: text/plain; charset="utf-8" We only check now for virObjectWait failures in virshRunConsole but we'd better check and for other failures too. Anyway if failure happened we need to shutdown console to stop delivering events from event loop thread or we are in trouble as console is freed on virshRunConsole exit. And we need to add refcounter to console object because event can be delivered after we remove fd handle/stream callback. Signed-off-by: Nikolay Shirokovskiy --- tools/virsh-console.c | 161 +++++++++++++++++++++++++++++++++++++---------= ---- 1 file changed, 119 insertions(+), 42 deletions(-) diff --git a/tools/virsh-console.c b/tools/virsh-console.c index 045a636..c0c3f90 100644 --- a/tools/virsh-console.c +++ b/tools/virsh-console.c @@ -60,9 +60,10 @@ struct virConsoleBuffer { typedef struct virConsole virConsole; typedef virConsole *virConsolePtr; struct virConsole { + virObjectLockable parent; + virStreamPtr st; bool quit; - virMutex lock; virCond cond; =20 int stdinWatch; @@ -74,6 +75,19 @@ struct virConsole { char escapeChar; }; =20 +static virClassPtr virConsoleClass; +static void virConsoleDispose(void *obj); + +static int +virConsoleOnceInit(void) +{ + if (!VIR_CLASS_NEW(virConsole, virClassForObjectLockable())) + return -1; + + return 0; +} + +VIR_ONCE_GLOBAL_INIT(virConsole); =20 static void virConsoleHandleSignal(int sig ATTRIBUTE_UNUSED) @@ -104,16 +118,14 @@ virConsoleShutdown(virConsolePtr con) =20 =20 static void -virConsoleFree(virConsolePtr con) +virConsoleDispose(void *obj) { - if (!con) - return; + virConsolePtr con =3D obj; =20 if (con->st) virStreamFree(con->st); - virMutexDestroy(&con->lock); + virCondDestroy(&con->cond); - VIR_FREE(con); } =20 =20 @@ -123,6 +135,12 @@ virConsoleEventOnStream(virStreamPtr st, { virConsolePtr con =3D opaque; =20 + virObjectLock(con); + + /* we got late event after console shutdowned */ + if (!con->st) + goto cleanup; + if (events & VIR_STREAM_EVENT_READABLE) { size_t avail =3D con->streamToTerminal.length - con->streamToTerminal.offset; @@ -132,7 +150,7 @@ virConsoleEventOnStream(virStreamPtr st, if (VIR_REALLOC_N(con->streamToTerminal.data, con->streamToTerminal.length + 1024) < 0) { virConsoleShutdown(con); - return; + goto cleanup; } con->streamToTerminal.length +=3D 1024; avail +=3D 1024; @@ -143,10 +161,10 @@ virConsoleEventOnStream(virStreamPtr st, con->streamToTerminal.offset, avail); if (got =3D=3D -2) - return; /* blocking */ + goto cleanup; /* blocking */ if (got <=3D 0) { virConsoleShutdown(con); - return; + goto cleanup; } con->streamToTerminal.offset +=3D got; if (con->streamToTerminal.offset) @@ -162,10 +180,10 @@ virConsoleEventOnStream(virStreamPtr st, con->terminalToStream.data, con->terminalToStream.offset); if (done =3D=3D -2) - return; /* blocking */ + goto cleanup; /* blocking */ if (done < 0) { virConsoleShutdown(con); - return; + goto cleanup; } memmove(con->terminalToStream.data, con->terminalToStream.data + done, @@ -187,6 +205,9 @@ virConsoleEventOnStream(virStreamPtr st, events & VIR_STREAM_EVENT_HANGUP) { virConsoleShutdown(con); } + + cleanup: + virObjectUnlock(con); } =20 =20 @@ -198,6 +219,12 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED, { virConsolePtr con =3D opaque; =20 + virObjectLock(con); + + /* we got late event after console shutdowned */ + if (!con->st) + goto cleanup; + if (events & VIR_EVENT_HANDLE_READABLE) { size_t avail =3D con->terminalToStream.length - con->terminalToStream.offset; @@ -207,7 +234,7 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED, if (VIR_REALLOC_N(con->terminalToStream.data, con->terminalToStream.length + 1024) < 0) { virConsoleShutdown(con); - return; + goto cleanup; } con->terminalToStream.length +=3D 1024; avail +=3D 1024; @@ -220,15 +247,15 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED, if (got < 0) { if (errno !=3D EAGAIN) virConsoleShutdown(con); - return; + goto cleanup; } if (got =3D=3D 0) { virConsoleShutdown(con); - return; + goto cleanup; } if (con->terminalToStream.data[con->terminalToStream.offset] =3D= =3D con->escapeChar) { virConsoleShutdown(con); - return; + goto cleanup; } =20 con->terminalToStream.offset +=3D got; @@ -242,6 +269,9 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED, events & VIR_EVENT_HANDLE_HANGUP) { virConsoleShutdown(con); } + + cleanup: + virObjectUnlock(con); } =20 =20 @@ -253,6 +283,12 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED, { virConsolePtr con =3D opaque; =20 + virObjectLock(con); + + /* we got late event after console shutdowned */ + if (!con->st) + goto cleanup; + if (events & VIR_EVENT_HANDLE_WRITABLE && con->streamToTerminal.offset) { ssize_t done; @@ -263,7 +299,7 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED, if (done < 0) { if (errno !=3D EAGAIN) virConsoleShutdown(con); - return; + goto cleanup; } memmove(con->streamToTerminal.data, con->streamToTerminal.data + done, @@ -285,6 +321,38 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED, events & VIR_EVENT_HANDLE_HANGUP) { virConsoleShutdown(con); } + + cleanup: + virObjectUnlock(con); +} + + +static virConsolePtr +virConsoleNew(void) +{ + virConsolePtr con; + + if (virConsoleInitialize() < 0) + return NULL; + + if (!(con =3D virObjectNew(virConsoleClass))) + return NULL; + + if (virCondInit(&con->cond) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot initialize console condition")); + + goto error; + } + + con->stdinWatch =3D -1; + con->stdoutWatch =3D -1; + + return con; + + error: + virObjectUnref(con); + return NULL; } =20 =20 @@ -324,6 +392,11 @@ virshRunConsole(vshControl *ctl, if (vshTTYMakeRaw(ctl, true) < 0) goto resettty; =20 + if (!(con =3D virConsoleNew())) + goto resettty; + + virObjectLock(con); + /* Trap all common signals so that we can safely restore the original * terminal settings on STDIN before the process exits - people don't = like * being left with a messed up terminal ! */ @@ -333,9 +406,6 @@ virshRunConsole(vshControl *ctl, sigaction(SIGHUP, &sighandler, &old_sighup); sigaction(SIGPIPE, &sighandler, &old_sigpipe); =20 - if (VIR_ALLOC(con) < 0) - goto cleanup; - con->escapeChar =3D virshGetEscapeChar(priv->escapeChar); con->st =3D virStreamNew(virDomainGetConnect(dom), VIR_STREAM_NONBLOCK); @@ -345,42 +415,49 @@ virshRunConsole(vshControl *ctl, if (virDomainOpenConsole(dom, dev_name, con->st, flags) < 0) goto cleanup; =20 - if (virCondInit(&con->cond) < 0 || virMutexInit(&con->lock) < 0) + virObjectRef(con); + if ((con->stdinWatch =3D virEventAddHandle(STDIN_FILENO, + VIR_EVENT_HANDLE_READABLE, + virConsoleEventOnStdin, + con, + virObjectFreeCallback)) < 0) { + virObjectUnref(con); goto cleanup; + } =20 - virMutexLock(&con->lock); - - con->stdinWatch =3D virEventAddHandle(STDIN_FILENO, - VIR_EVENT_HANDLE_READABLE, - virConsoleEventOnStdin, - con, - NULL); - con->stdoutWatch =3D virEventAddHandle(STDOUT_FILENO, - 0, - virConsoleEventOnStdout, - con, - NULL); + virObjectRef(con); + if ((con->stdoutWatch =3D virEventAddHandle(STDOUT_FILENO, + 0, + virConsoleEventOnStdout, + con, + virObjectFreeCallback)) < 0)= { + virObjectUnref(con); + goto cleanup; + } =20 - virStreamEventAddCallback(con->st, - VIR_STREAM_EVENT_READABLE, - virConsoleEventOnStream, - con, - NULL); + virObjectRef(con); + if (virStreamEventAddCallback(con->st, + VIR_STREAM_EVENT_READABLE, + virConsoleEventOnStream, + con, + virObjectFreeCallback) < 0) { + virObjectUnref(con); + goto cleanup; + } =20 while (!con->quit) { - if (virCondWait(&con->cond, &con->lock) < 0) { - virMutexUnlock(&con->lock); + if (virCondWait(&con->cond, &con->parent.lock) < 0) { VIR_ERROR(_("unable to wait on console condition")); goto cleanup; } } =20 - virMutexUnlock(&con->lock); - ret =3D 0; =20 cleanup: - virConsoleFree(con); + virConsoleShutdown(con); + virObjectUnlock(con); + virObjectUnref(con); =20 /* Restore original signal handlers */ sigaction(SIGQUIT, &old_sigquit, NULL); --=20 1.8.3.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Sat May 4 03:51:35 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1550241658183683.0638438662797; Fri, 15 Feb 2019 06:40:58 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9F546C0D7F1F; Fri, 15 Feb 2019 14:40:55 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6751460C62; Fri, 15 Feb 2019 14:40:55 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id F11D43F605; Fri, 15 Feb 2019 14:40:54 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x1FEerwh003115 for ; Fri, 15 Feb 2019 09:40:53 -0500 Received: by smtp.corp.redhat.com (Postfix) id 2D985102493E; Fri, 15 Feb 2019 14:40:53 +0000 (UTC) Received: from mx1.redhat.com (ext-mx07.extmail.prod.ext.phx2.redhat.com [10.5.110.31]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 233361024932 for ; Fri, 15 Feb 2019 14:40:47 +0000 (UTC) Received: from relay.sw.ru (relay.sw.ru [185.231.240.75]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0C342C0AC91D for ; Fri, 15 Feb 2019 14:40:45 +0000 (UTC) Received: from [10.94.3.220] (helo=dim-vz7.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1guefS-0005Db-Qw for libvir-list@redhat.com; Fri, 15 Feb 2019 17:40:42 +0300 From: Nikolay Shirokovskiy To: libvir-list@redhat.com Date: Fri, 15 Feb 2019 17:39:35 +0300 Message-Id: <1550241575-871081-3-git-send-email-nshirokovskiy@virtuozzo.com> In-Reply-To: <1550241575-871081-1-git-send-email-nshirokovskiy@virtuozzo.com> References: <1550241575-871081-1-git-send-email-nshirokovskiy@virtuozzo.com> X-Greylist: Sender passed SPF test, ACL 242 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 15 Feb 2019 14:40:46 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 15 Feb 2019 14:40:46 +0000 (UTC) for IP:'185.231.240.75' DOMAIN:'relay.sw.ru' HELO:'relay.sw.ru' FROM:'nshirokovskiy@virtuozzo.com' RCPT:'' X-RedHat-Spam-Score: -0.001 (SPF_PASS) 185.231.240.75 relay.sw.ru 185.231.240.75 relay.sw.ru X-Scanned-By: MIMEDefang 2.78 on 10.5.110.31 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 2/2] tools: console: pass stream/fd errors to user X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Fri, 15 Feb 2019 14:40:56 +0000 (UTC) Content-Type: text/plain; charset="utf-8" If console disconnected due to connection problem or problem on server side for example it is convinient to provide the cause to the user. If error comes from API then error is saved in virsh global variable but as we return success from virshRunConsole if we reach waiting stage then error is never reported. Let's track for error in 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. Let's also add missing error reports in code. Signed-off-by: Nikolay Shirokovskiy --- 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; =20 char escapeChar; + virError error; }; =20 static virClassPtr virConsoleClass; @@ -98,6 +99,11 @@ virConsoleHandleSignal(int sig ATTRIBUTE_UNUSED) static void virConsoleShutdown(virConsolePtr con) { + virErrorPtr err =3D virGetLastError(); + + if (con->error.code =3D=3D VIR_ERR_OK && err && err->code !=3D 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); =20 virCondDestroy(&con->cond); + virResetError(&con->error); } =20 =20 @@ -162,7 +169,13 @@ virConsoleEventOnStream(virStreamPtr st, avail); if (got =3D=3D -2) goto cleanup; /* blocking */ - if (got <=3D 0) { + if (got =3D=3D 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("console stream EOF")); + virConsoleShutdown(con); + goto cleanup; + } + if (got < 0) { virConsoleShutdown(con); goto cleanup; } @@ -245,11 +258,14 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED, con->terminalToStream.offset, avail); if (got < 0) { - if (errno !=3D EAGAIN) + if (errno !=3D EAGAIN) { + virReportSystemError(errno, "%s", _("can not read from std= in")); virConsoleShutdown(con); + } goto cleanup; } if (got =3D=3D 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); } =20 - 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; } =20 cleanup: @@ -297,8 +320,10 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED, con->streamToTerminal.data, con->streamToTerminal.offset); if (done < 0) { - if (errno !=3D EAGAIN) + if (errno !=3D EAGAIN) { + virReportSystemError(errno, "%s", _("can not write to stdo= ut")); 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); =20 - 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; } =20 cleanup: @@ -447,15 +479,24 @@ virshRunConsole(vshControl *ctl, =20 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; } } =20 - ret =3D 0; + if (con->error.code =3D=3D VIR_ERR_OK) + ret =3D 0; =20 cleanup: virConsoleShutdown(con); + + if (ret < 0) { + vshResetLibvirtError(); + virSetError(&con->error); + vshSaveLibvirtHelperError(); + } + virObjectUnlock(con); virObjectUnref(con); =20 --=20 1.8.3.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list