From nobody Mon Feb 9 09:33:59 2026 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 1552463007532128.09549999086153; Wed, 13 Mar 2019 00:43:27 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A4183308C392; Wed, 13 Mar 2019 07:43:25 +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 34C56171C2; Wed, 13 Mar 2019 07:43:24 +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 BE4A841F3C; Wed, 13 Mar 2019 07:43:21 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x2D7h6bS009636 for ; Wed, 13 Mar 2019 03:43:07 -0400 Received: by smtp.corp.redhat.com (Postfix) id C434A5E7A5; Wed, 13 Mar 2019 07:43:06 +0000 (UTC) Received: from mx1.redhat.com (ext-mx17.extmail.prod.ext.phx2.redhat.com [10.5.110.46]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BFD6C5DD84 for ; Wed, 13 Mar 2019 07:43:04 +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 A64023089E71 for ; Wed, 13 Mar 2019 07:43:02 +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 1h3yXU-0000pk-7Y for libvir-list@redhat.com; Wed, 13 Mar 2019 10:43:00 +0300 From: Nikolay Shirokovskiy To: libvir-list@redhat.com Date: Wed, 13 Mar 2019 10:39:46 +0300 Message-Id: <1552462789-715109-2-git-send-email-nshirokovskiy@virtuozzo.com> In-Reply-To: <1552462789-715109-1-git-send-email-nshirokovskiy@virtuozzo.com> References: <1552462789-715109-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.46]); Wed, 13 Mar 2019 07:43:03 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Wed, 13 Mar 2019 07:43:03 +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.84 on 10.5.110.46 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 1/4] 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.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Wed, 13 Mar 2019 07:43:26 +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. We need to turn console into virObject object because stream/fd callbacks can be called from a event loop thread after shutdown/freeing console in main thread. It is convinient to turn into virLockableObject as we have mutex in console object. Signed-off-by: Nikolay Shirokovskiy --- tools/virsh-console.c | 122 +++++++++++++++++++++++++++++++++++-----------= ---- 1 file changed, 87 insertions(+), 35 deletions(-) diff --git a/tools/virsh-console.c b/tools/virsh-console.c index 045a636..9289221 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) @@ -98,22 +112,22 @@ virConsoleShutdown(virConsolePtr con) virEventRemoveHandle(con->stdoutWatch); con->stdinWatch =3D -1; con->stdoutWatch =3D -1; - con->quit =3D true; - virCondSignal(&con->cond); + if (!con->quit) { + con->quit =3D true; + virCondSignal(&con->cond); + } } =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 @@ -288,6 +302,35 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED, } =20 =20 +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; +} + + static char virshGetEscapeChar(const char *s) { @@ -324,6 +367,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 +381,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 +390,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; + } + + virObjectRef(con); + if ((con->stdoutWatch =3D virEventAddHandle(STDOUT_FILENO, + 0, + virConsoleEventOnStdout, + 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); - - 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