From nobody Sat Feb 7 06:20:29 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1749111168; cv=none; d=zohomail.com; s=zohoarc; b=Es8uRFo8vPUtYZUUkGqUqR24dzMAOu2Ck4XqH9m11TWgmuHeDmi0XrSYGNC0ZqcNxBE2RJeYL/4o8O/yVZBEWrMXrRwo0CnGnaKVu8+4M4ULcWpuhm2ym5cqawzU/Rl5Wo7z3vacytfGxrmHYgY4XpPL3TXivj6FqDvyda7X7v8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1749111168; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=hRtHb5xfmOMbW36LH4lOLbnEQBRuVTWkApLbtl2GonE=; b=aqNWQP+LU/SH8zR+F0Ai7xhUabrDPE7XMKPqdBqOXhQnJQQoeZMSaSjEkb1RvsueftmZKgCEnR3zwZ1gCfWdrAcP0GHjbllVavJjeWGVftZTixGha8NQsxbEaQf55Q2LxvYEmvuZfV7yQxTaeebIuCC266ohXYsud9L9u7yxPls= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1749111168540376.16305212809493; Thu, 5 Jun 2025 01:12:48 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 49F6811E1; Thu, 5 Jun 2025 04:12:47 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 1204B1435; Thu, 5 Jun 2025 04:11:06 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id D1127A11; Thu, 5 Jun 2025 04:10:56 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 4B5CEA02 for ; Thu, 5 Jun 2025 04:10:56 -0400 (EDT) Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-587-CBstnv0yPfW14xsfteEDwA-1; Thu, 05 Jun 2025 04:10:54 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E2A1318001D6 for ; Thu, 5 Jun 2025 08:10:53 +0000 (UTC) Received: from speedmetal.redhat.com (unknown [10.44.22.3]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2875018003FC for ; Thu, 5 Jun 2025 08:10:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1749111056; h=from:from: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: in-reply-to:in-reply-to:references:references; bh=iRs2YrEDYAB9+AHzxq1lVyOKkDmew+MvMKDwyp3//pk=; b=QsYib9gLQT3sVg1E6CsGA2B2Uj+B9x4lDnN4w6+GsU7dkjuZSha1MLoorMFWi5itqYWEBT /yyGrvzmPdb35FQIusFyAgIitC87CBVv91wtCGdOtA0M2PTa5Z0Rllm5aIvbjWCtnMnBzt qEe0xLFunxOhckDcNXD8HPDz8ipdIwM= X-MC-Unique: CBstnv0yPfW14xsfteEDwA-1 X-Mimecast-MFC-AGG-ID: CBstnv0yPfW14xsfteEDwA_1749111054 To: devel@lists.libvirt.org Subject: [PATCH 3/7] virsh: cmdEvent: Ensure that event callbacks are unregistered before returning Date: Thu, 5 Jun 2025 10:10:43 +0200 Message-ID: <9589d6d2a674173fcd53dec0aa0f6ab5decd55fc.1749110902.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: AC8eJbAHySAfWxWbGgE9IxZEhP9Xf1QclCgYQ3mRyvQ_1749111054 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: JXBCOF72NT545QMUJREOYDTWFLCC3LEK X-Message-ID-Hash: JXBCOF72NT545QMUJREOYDTWFLCC3LEK X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: Peter Krempa via Devel Reply-To: Peter Krempa X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1749111169927116600 Content-Type: text/plain; charset="utf-8" From: Peter Krempa Successful return from 'virConnectDomainEventDeregisterAny' does not guarantee that there aren't still in-progress events being handled by the callbacks. Since 'cmdEvent' passes in a slice from an array as the private data of the callbacks, we must ensure that the array stays in scope (it's auto-freed) for the whole time there are possible callbacks being executed. While in practice this doesn't happen as the callbacks are usually quick enough to finish while unregistering stuff, placing a 'sleep(1)' into e.g. 'virshEventLifecyclePrint' and starting a domain results in crash of virsh with the following backtrace: Program terminated with signal SIGSEGV, Segmentation fault. #0 0x00005557b5cfd343 in virshEventPrintf (data=3Ddata@entry=3D0x5557db96= 19b0, fmt=3Dfmt@entry=3D0x5557b5d5e527 "%s") at ../../../libvirt/tools/virs= h-domain-event.c:252 Thread 2 (Thread 0x7f59a54b7d00 (LWP 2097121)): #0 0x00007f59a6cadbf9 in __futex_abstimed_wait_common () at /lib64/libc.s= o.6 #1 0x00007f59a6cb2cf3 in __pthread_clockjoin_ex () at /lib64/libc.so.6 #2 0x00005557b5cd57f6 in virshDeinit (ctl=3D0x7ffc7b615140) at ../../../l= ibvirt/tools/virsh.c:408 #3 0x00005557b5cd5391 in main (argc=3D, argv=3D) at ../../../libvirt/tools/virsh.c:932 Thread 1 (Thread 0x7f59a51a66c0 (LWP 2097122)): #0 0x00005557b5cfd343 in virshEventPrintf (data=3Ddata@entry=3D0x5557db96= 19b0, fmt=3Dfmt@entry=3D0x5557b5d5e527 "%s") at ../../../libvirt/tools/virs= h-domain-event.c:252 #1 0x00005557b5cffa10 in virshEventPrint (data=3D0x5557db9619b0, buf=3D0x= 7f59a51a55c0) at ../../../libvirt/tools/virsh-domain-event.c:290 #2 virshEventLifecyclePrint (conn=3D, dom=3D, event=3D, detail=3D, opaque=3D0x5557db9619= b0) at ../../../libvirt/ [snipped] From the backtrace you can see that the 'main()' thread is already shutting down virsh, which means that 'cmdEvent' terminated and the private data was freed. The event loop thread is still execing the callback which accesses the data. To fix this add a condition and wait on all of the callbacks to be unregistered first (their private data freeing function will be called). This bug was observed when I've copied the event code for a new virsh command which had a bit more involved callbacks. Fixes: 99fa96c3907 Signed-off-by: Peter Krempa --- tools/virsh-domain-event.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/tools/virsh-domain-event.c b/tools/virsh-domain-event.c index 69a68d857d..9aa21b2e78 100644 --- a/tools/virsh-domain-event.c +++ b/tools/virsh-domain-event.c @@ -237,10 +237,23 @@ struct virshDomEventData { bool timestamp; virshDomainEventCallback *cb; int id; + + virMutex *m; /* needed to signal that handler was unregistered for cle= an shutdown */ + virCond *c; }; typedef struct virshDomEventData virshDomEventData; +static void +virshDomEventDataUnregistered(virshDomEventData *d) +{ + g_auto(virLockGuard) name =3D virLockGuardLock(d->m); + /* signal that the handler was unregistered */ + d->id =3D -1; + virCondSignal(d->c); +} + + static void G_GNUC_PRINTF(2, 3) virshEventPrintf(virshDomEventData *data, const char *fmt, @@ -936,6 +949,8 @@ cmdEvent(vshControl *ctl, const vshCmd *cmd) bool timestamp =3D vshCommandOptBool(cmd, "timestamp"); int count =3D 0; virshControl *priv =3D ctl->privData; + g_auto(virMutex) m =3D VIR_MUTEX_INITIALIZER; + g_auto(virCond) c =3D VIR_COND_INITIALIZER; VSH_EXCLUSIVE_OPTIONS("all", "event"); VSH_EXCLUSIVE_OPTIONS("list", "all"); @@ -969,6 +984,8 @@ cmdEvent(vshControl *ctl, const vshCmd *cmd) data[ndata].count =3D &count; data[ndata].timestamp =3D timestamp; data[ndata].cb =3D &virshDomainEventCallbacks[i]; + data[ndata].m =3D &m; + data[ndata].c =3D &c; data[ndata].id =3D -1; ndata++; } @@ -994,7 +1011,7 @@ cmdEvent(vshControl *ctl, const vshCmd *cmd) data[i].event, data[i].cb->cb, &data[i], - NULL)) < 0) { + (virFreeCallbac= k) virshDomEventDataUnregistered)) < 0) { /* When registering for all events: if the first * registration succeeds, silently ignore failures on all * later registrations on the assumption that the server @@ -1022,14 +1039,27 @@ cmdEvent(vshControl *ctl, const vshCmd *cmd) ret =3D true; cleanup: - vshEventCleanup(ctl); if (data) { for (i =3D 0; i < ndata; i++) { if (data[i].id >=3D 0 && virConnectDomainEventDeregisterAny(priv->conn, data[i].id)= < 0) ret =3D false; } + + virMutexLock(&m); + while (true) { + for (i =3D 0; i < ndata; i++) { + if (data[i].id >=3D 0) + break; + } + + if (i =3D=3D ndata || + virCondWait(&c, &m) < 0) + break; + } + virMutexUnlock(&m); } + vshEventCleanup(ctl); return ret; } --=20 2.49.0