From nobody Sun Nov 16 02:28:33 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1762643570; cv=none; d=zohomail.com; s=zohoarc; b=cGlZuoDITktXJANwGZH2VirjtZ6+cYNAXK2LEl6PZ64f3DPX7F7jgTksyNLy28fprM2PfCIjWIyRCi/allV4vAUjT4nZsFfnCmw+i05FhWRIXbqEBUKItqndOyhc1lyvEHbratNweTo+LdhRd2Al20rF0Jr6drJRzd4iuT+gqIk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762643570; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=xpXc3S2Q3NrPCkGXSUoupnhbTvu0TcNTPyx71+k/Gxw=; b=j+D9W4xVmAfayPS9qZY1ZVOK7nZYsrhCRuKdDC7ggKWe17pytO/Plxi2h5o/z4KIx0o4djQfRce64gq55Rc7nsqEFPSD8jO/Qd+BAuw6XpkKUQL9fC0ZbrBFlktRt0FvJZ/AOdEhwwB5tr1pcW5KdTAD+yzjrRy9rWG/gjh5N0U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1762643570823223.2626723418149; Sat, 8 Nov 2025 15:12:50 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vHs0I-0005cd-8b; Sat, 08 Nov 2025 18:05:54 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vHs07-0005Ov-Iy for qemu-devel@nongnu.org; Sat, 08 Nov 2025 18:05:43 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vHs05-0001fG-JJ for qemu-devel@nongnu.org; Sat, 08 Nov 2025 18:05:43 -0500 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-563-FOCQtf0HPKKJ8mPuSzrzeQ-1; Sat, 08 Nov 2025 18:05:39 -0500 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 17385195605F; Sat, 8 Nov 2025 23:05:38 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.2]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CCF2419560A7; Sat, 8 Nov 2025 23:05:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762643140; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xpXc3S2Q3NrPCkGXSUoupnhbTvu0TcNTPyx71+k/Gxw=; b=grL3H4VdfvZocareeZJQeXy3kBr058YEmB1PWr+ouiKBNeGm1SS2a01dPTCyho2oGygYhe cugEnGOiyTXbjCRL1BBZH7MNmVrkCMDjb3MKjdn+gWpqekutzk73JyEQs7IUjeKT9o3NmJ uy1jzg7a/FaopKWUM1HHlTYZHIdYPDQ= X-MC-Unique: FOCQtf0HPKKJ8mPuSzrzeQ-1 X-Mimecast-MFC-AGG-ID: FOCQtf0HPKKJ8mPuSzrzeQ_1762643138 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, berrange@redhat.com, kwolf@redhat.com, qemu-stable@nongnu.org Subject: [PATCH v2 04/12] qio: Remember context of qio_net_listener_set_client_func_full Date: Sat, 8 Nov 2025 16:59:25 -0600 Message-ID: <20251108230525.3169174-18-eblake@redhat.com> In-Reply-To: <20251108230525.3169174-14-eblake@redhat.com> References: <20251108230525.3169174-14-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1762643573227158500 Content-Type: text/plain; charset="utf-8" io/net-listener.c has two modes of use: asynchronous (the user calls qio_net_listener_set_client_func to wake up the callback via the global GMainContext, or qio_net_listener_set_client_func_full to wake up the callback via the caller's own alternative GMainContext), and synchronous (the user calls qio_net_listener_wait_client which creates its own GMainContext and waits for the first client connection before returning, with no need for a user's callback). But commit 938c8b79 has a latent logic flaw: when qio_net_listener_wait_client finishes on its temporary context, it reverts all of the siocs back to the global GMainContext rather than the potentially non-NULL context they might have been originally registered with. Similarly, if the user creates a net-listener, adds initial addresses, registers an async callback with a non-default context (which ties to all siocs for the initial addresses), then adds more addresses with qio_net_listener_add, the siocs for later addresses are blindly placed in the global context, rather than sharing the context of the earlier ones. In practice, I don't think this has caused issues. As pointed out by the original commit, all async callers prior to that commit were already okay with the NULL default context; and the typical usage pattern is to first add ALL the addresses the listener will pay attention to before ever setting the async callback. Likewise, if a file uses only qio_net_listener_set_client_func instead of qio_net_listener_set_client_func_full, then it is never using a custom context, so later assignments of async callbacks will still be to the same global context as earlier ones. Meanwhile, any callers that want to do the sync operation to grab the first client are unlikely to register an async callback; altogether bypassing the question of whether later assignments of a GSource are being tied to a different context over time. I do note that chardev/char-socket.c is the only file that calls both qio_net_listener_wait_client (sync for a single client in tcp_chr_accept_server_sync), and qio_net_listener_set_client_func_full (several places, all with chr->gcontext, but sometimes with a NULL callback function during teardown). But as far as I can tell, the two uses are mutually exclusive, based on the is_waitconnect parameter to qmp_chardev_open_socket_server. That said, it is more robust to remember when an async callback function is tied to a non-default context, and have both the sync wait and any late address additions honor that same context. That way, the code will be robust even if a later user performs a sync wait for a specific client in the middle of servicing a longer-lived QIONetListener that has an async callback for all other clients. CC: qemu-stable@nongnu.org Fixes: 938c8b79 ("qio: store gsources for net listeners", v2.12.0) Signed-off-by: Eric Blake Reviewed-by: Daniel P. Berrang=C3=A9 --- v2: move earlier in series, trace context --- include/io/net-listener.h | 1 + io/net-listener.c | 25 ++++++++++++++++--------- io/trace-events | 6 +++--- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/include/io/net-listener.h b/include/io/net-listener.h index ab9f291ed62..42fbfab5467 100644 --- a/include/io/net-listener.h +++ b/include/io/net-listener.h @@ -50,6 +50,7 @@ struct QIONetListener { QIOChannelSocket **sioc; GSource **io_source; size_t nsioc; + GMainContext *context; bool connected; diff --git a/io/net-listener.c b/io/net-listener.c index d71b65270e0..0f16b78fbbd 100644 --- a/io/net-listener.c +++ b/io/net-listener.c @@ -51,7 +51,8 @@ static gboolean qio_net_listener_channel_func(QIOChannel = *ioc, return TRUE; } - trace_qio_net_listener_callback(listener, listener->io_func); + trace_qio_net_listener_callback(listener, listener->io_func, + listener->context); if (listener->io_func) { listener->io_func(listener, sioc, listener->io_data); } @@ -125,13 +126,14 @@ void qio_net_listener_add(QIONetListener *listener, object_ref(OBJECT(sioc)); listener->connected =3D true; - trace_qio_net_listener_watch(listener, listener->io_func, "add"); + trace_qio_net_listener_watch(listener, listener->io_func, + listener->context, "add"); if (listener->io_func !=3D NULL) { object_ref(OBJECT(listener)); listener->io_source[listener->nsioc] =3D qio_channel_add_watch_sou= rce( QIO_CHANNEL(listener->sioc[listener->nsioc]), G_IO_IN, qio_net_listener_channel_func, - listener, (GDestroyNotify)object_unref, NULL); + listener, (GDestroyNotify)object_unref, listener->context); } listener->nsioc++; @@ -147,7 +149,8 @@ void qio_net_listener_set_client_func_full(QIONetListen= er *listener, size_t i; trace_qio_net_listener_unwatch(listener, listener->io_func, - "set_client_func"); + listener->context, "set_client_func"); + for (i =3D 0; i < listener->nsioc; i++) { if (listener->io_source[i]) { g_source_destroy(listener->io_source[i]); @@ -162,9 +165,10 @@ void qio_net_listener_set_client_func_full(QIONetListe= ner *listener, listener->io_func =3D func; listener->io_data =3D data; listener->io_notify =3D notify; + listener->context =3D context; trace_qio_net_listener_watch(listener, listener->io_func, - "set_client_func"); + listener->context, "set_client_func"); if (listener->io_func !=3D NULL) { for (i =3D 0; i < listener->nsioc; i++) { object_ref(OBJECT(listener)); @@ -225,7 +229,8 @@ QIOChannelSocket *qio_net_listener_wait_client(QIONetLi= stener *listener) }; size_t i; - trace_qio_net_listener_unwatch(listener, listener->io_func, "wait_clie= nt"); + trace_qio_net_listener_unwatch(listener, listener->io_func, + listener->context, "wait_client"); for (i =3D 0; i < listener->nsioc; i++) { if (listener->io_source[i]) { g_source_destroy(listener->io_source[i]); @@ -255,14 +260,15 @@ QIOChannelSocket *qio_net_listener_wait_client(QIONet= Listener *listener) g_main_loop_unref(loop); g_main_context_unref(ctxt); - trace_qio_net_listener_watch(listener, listener->io_func, "wait_client= "); + trace_qio_net_listener_watch(listener, listener->io_func, + listener->context, "wait_client"); if (listener->io_func !=3D NULL) { for (i =3D 0; i < listener->nsioc; i++) { object_ref(OBJECT(listener)); listener->io_source[i] =3D qio_channel_add_watch_source( QIO_CHANNEL(listener->sioc[i]), G_IO_IN, qio_net_listener_channel_func, - listener, (GDestroyNotify)object_unref, NULL); + listener, (GDestroyNotify)object_unref, listener->context); } } @@ -277,7 +283,8 @@ void qio_net_listener_disconnect(QIONetListener *listen= er) return; } - trace_qio_net_listener_unwatch(listener, listener->io_func, "disconnec= t"); + trace_qio_net_listener_unwatch(listener, listener->io_func, + listener->context, "disconnect"); for (i =3D 0; i < listener->nsioc; i++) { if (listener->io_source[i]) { g_source_destroy(listener->io_source[i]); diff --git a/io/trace-events b/io/trace-events index 10976eca5fe..0cb77d579b6 100644 --- a/io/trace-events +++ b/io/trace-events @@ -74,6 +74,6 @@ qio_channel_command_abort(void *ioc, int pid) "Command ab= ort ioc=3D%p pid=3D%d" qio_channel_command_wait(void *ioc, int pid, int ret, int status) "Command= abort ioc=3D%p pid=3D%d ret=3D%d status=3D%d" # net-listener.c -qio_net_listener_watch(void *listener, void *func, const char *extra) "Net= listener=3D%p watch enabled func=3D%p by %s" -qio_net_listener_unwatch(void *listener, void *func, const char *extra) "N= et listener=3D%p watch disabled func=3D%p by %s" -qio_net_listener_callback(void *listener, void *func) "Net listener=3D%p c= allback forwarding to func=3D%p" +qio_net_listener_watch(void *listener, void *func, void *ctx, const char *= extra) "Net listener=3D%p watch enabled func=3D%p ctx=3D%p by %s" +qio_net_listener_unwatch(void *listener, void *func, void *ctx, const char= *extra) "Net listener=3D%p watch disabled func=3D%p ctx=3D%p by %s" +qio_net_listener_callback(void *listener, void *func, void *ctx) "Net list= ener=3D%p callback forwarding to func=3D%p ctx=3D%p" --=20 2.51.1