From nobody Sun Feb 8 01:37:20 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) client-ip=207.211.31.81; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1596045834; cv=none; d=zohomail.com; s=zohoarc; b=dSDzqZRpv7oQa/bjokaD9oZOGkc4K5sphefdx1QJ0FsNXYp2p1x9GZzBG5fmX8y1KMTw0tUbvgmZvs4r6lDi/gO0rIoclFSSImSrrkesLOrVk+a3aoWvoEZgtNiHr6mz1B198wr6uZ0aDnwJxp8hfzs5+NyCXblLixJftLEWUuQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1596045834; h=Content-Type:Content-Transfer-Encoding:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=2s4j/zzLH0FEvS1sA44Tgn2td+PQg4mWQuD13Mt4EmY=; b=jT/ga8Ui3bkcbs2NY/q0ldRvVbyx9LhndsNF4Cq1aLRoIrrWtWeJtWrKOJ+MA20+zCToA6RCKJgDRVFKtq0zIz4sfJelTPes5tn3beYCCgkoRu2A0yK9jYcuwS4Nk+DeZqFpsRUUOx61cwUqIdKN6ahxqdMO/T/+L7XAU+BrVr0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by mx.zohomail.com with SMTPS id 1596045834772184.1825630027081; Wed, 29 Jul 2020 11:03:54 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-409-OMVGBiZLOG-0UEFgdbRHZQ-1; Wed, 29 Jul 2020 14:03:51 -0400 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 mimecast-mx01.redhat.com (Postfix) with ESMTPS id E764310059A8; Wed, 29 Jul 2020 18:03:44 +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 EB7F75DA72; Wed, 29 Jul 2020 18:03:42 +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 2CC0E95A62; Wed, 29 Jul 2020 18:03:40 +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 06TI3cFM022417 for ; Wed, 29 Jul 2020 14:03:38 -0400 Received: by smtp.corp.redhat.com (Postfix) id A8A1310013D0; Wed, 29 Jul 2020 18:03:38 +0000 (UTC) Received: from domokun.gsslab.fab.redhat.com (unknown [10.33.8.110]) by smtp.corp.redhat.com (Postfix) with ESMTP id 140E01002388; Wed, 29 Jul 2020 18:03:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1596045833; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=2s4j/zzLH0FEvS1sA44Tgn2td+PQg4mWQuD13Mt4EmY=; b=cfbtWNwMrKWXngOnDH8Pfrn5+DAURKffFYxjliTZWNuOs0p5RPJ7/f37Pbv5cBxJJPFM67 FATp/9eyY0nPqjAD52vTcXOAm1uaGC2hjJk7hAW2AS3dIANNfAF46Bftmq+e/E/oozFrES B3tAeIZjZaxyMQ00jze7Zt8QFUYcz14= X-MC-Unique: OMVGBiZLOG-0UEFgdbRHZQ-1 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Subject: [PATCH] qemu: fix race in signal interrupt during QEMU startup Date: Wed, 29 Jul 2020 19:03:32 +0100 Message-Id: <20200729180332.2798261-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-loop: libvir-list@redhat.com 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: , 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-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) If a Ctrl-C arrives while we are in the middle of executing the virDomainCreateXML call, we will have no "virDomainPtr" object available, but QEMU may none the less be running. This means we'll never try to stop the QEMU process before we honour the Ctrl-C and exit. To deal with this race we need to postpone quit of the event loop if it is requested while in the middle of domain startup. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- src/qemu/qemu_shim.c | 77 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_shim.c b/src/qemu/qemu_shim.c index 7e87b8fb96..bbcf9dc886 100644 --- a/src/qemu/qemu_shim.c +++ b/src/qemu/qemu_shim.c @@ -30,19 +30,61 @@ =20 #define VIR_FROM_THIS VIR_FROM_QEMU =20 +static GMutex eventLock; +static bool eventNoQuitFlag; static bool eventQuitFlag; static int eventQuitFD =3D -1; static virDomainPtr dom; =20 +/* Runs in event loop thread context */ static void * qemuShimEventLoop(void *opaque G_GNUC_UNUSED) { - while (!eventQuitFlag) + bool quit =3D false; + while (!quit) { + g_mutex_lock(&eventLock); + if (eventQuitFlag && !eventNoQuitFlag) { + if (dom) { + virDomainDestroy(dom); + quit =3D true; + } + } + g_mutex_unlock(&eventLock); virEventRunDefaultImpl(); + } =20 return NULL; } =20 +/* Runs in any thread context */ +static bool +qemuShimEventLoopPreventQuit(void) +{ + bool quitting; + g_mutex_lock(&eventLock); + quitting =3D eventQuitFlag; + if (!quitting) + eventNoQuitFlag =3D true; + g_mutex_unlock(&eventLock); + return quitting; +} + +/* Runs in any thread context */ +static bool +qemuShimEventLoopAllowQuit(void) +{ + bool quitting; + g_mutex_lock(&eventLock); + eventNoQuitFlag =3D false; + /* kick the event loop thread again immediately */ + quitting =3D eventQuitFlag; + if (quitting) + ignore_value(safewrite(eventQuitFD, "c", 1)); + g_mutex_unlock(&eventLock); + return quitting; +} + + /* Runs in event loop thread context */ static void qemuShimEventLoopStop(int watch G_GNUC_UNUSED, @@ -52,7 +94,9 @@ qemuShimEventLoopStop(int watch G_GNUC_UNUSED, { char c; ignore_value(read(fd, &c, 1)); + g_mutex_lock(&eventLock); eventQuitFlag =3D true; + g_mutex_unlock(&eventLock); } =20 /* Runs in event loop thread context */ @@ -63,8 +107,11 @@ qemuShimDomShutdown(virConnectPtr econn G_GNUC_UNUSED, int detail G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { - if (event =3D=3D VIR_DOMAIN_EVENT_STOPPED) + if (event =3D=3D VIR_DOMAIN_EVENT_STOPPED) { + g_mutex_lock(&eventLock); eventQuitFlag =3D true; + g_mutex_unlock(&eventLock); + } =20 return 0; } @@ -109,6 +156,7 @@ int main(int argc, char **argv) { 0 } }; int quitfd[2] =3D {-1, -1}; + bool quitting; long long start =3D g_get_monotonic_time(); =20 #define deltams() ((long long)g_get_monotonic_time() - start) @@ -128,8 +176,8 @@ int main(int argc, char **argv) } =20 if (verbose) - g_printerr("%s: %lld: initializing libvirt\n", - argv[0], deltams()); + g_printerr("%s: %lld: initializing libvirt %d\n", + argv[0], deltams(), gettid()); =20 if (virInitialize() < 0) { g_printerr("%s: cannot initialize libvirt\n", argv[0]); @@ -277,7 +325,7 @@ int main(int argc, char **argv) } =20 if (verbose) - g_printerr("%s: %lld: starting guest %s\n", + g_printerr("%s: %lld: fetching guest config %s\n", argv[0], deltams(), argv[1]); =20 if (!g_file_get_contents(argv[1], &xml, NULL, &error)) { @@ -286,7 +334,24 @@ int main(int argc, char **argv) goto cleanup; } =20 + if (verbose) + g_printerr("%s: %lld: starting guest %s\n", + argv[0], deltams(), argv[1]); + + /* + * If the user issues a ctrl-C at this time, we need to + * let the virDomainCreateXML call complete, so that we + * can then clean up the guest correctly. We must also + * ensure that the event loop doesn't quit yet, because + * it might be needed to complete VM startup & shutdown + * during the cleanup. + */ + quitting =3D qemuShimEventLoopPreventQuit(); + if (quitting) + goto cleanup; dom =3D virDomainCreateXML(conn, xml, 0); + quitting =3D qemuShimEventLoopAllowQuit(); + if (!dom) { g_printerr("%s: cannot start VM: %s\n", argv[0], virGetLastErrorMessage()); @@ -295,6 +360,8 @@ int main(int argc, char **argv) if (verbose) g_printerr("%s: %lld: guest running, Ctrl-C to stop now\n", argv[0], deltams()); + if (quitting) + goto cleanup; =20 if (debug) { g_autofree char *newxml =3D NULL; --=20 2.24.1