From nobody Sat Sep 26 01:39:34 2026 Received: from mail-yw1-f172.google.com (mail-yw1-f172.google.com [209.85.128.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E6FC03BD647 for ; Sun, 6 Sep 2026 17:18:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788715093; cv=none; b=DuU3/6Q+Wt6roQGLL2fKYSvsAf6GZlldXEVACVf5VnOwbKD9qSuMDs1rTva7blHpOjzHODofapB/meWocm+oRu+SbQaqYuH+RF+7xo9z680T3lMJhGd3P9XP0V+fJcxxth8VGet82DlzC7mjlQFF38wxglg83GXeCoyee4gPErs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788715093; c=relaxed/simple; bh=BZym0wR4Aan5tMbnGysaaT/iwspZu2YkmN/kFum26dw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WqaNB/dlP9yGn1L9inxE65K50wuUxOVpZPc7P5ltXH7/KvOeY+S1cL6H6pTTN6LAappeAEysFPW5tVmDKljKfpDi/A363VDCPryoeB9qnJW/OoN5NrZ6wUjYL7Qhu/hJwIueMJ+vNmgSwOVkJosTKOhLLBjSNw6/nlATK0iL4+w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=qnbw7rb1; arc=none smtp.client-ip=209.85.128.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qnbw7rb1" Received: by mail-yw1-f172.google.com with SMTP id 00721157ae682-8588583a7c3so26605037b3.2 for ; Sun, 06 Sep 2026 10:18:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788715090; x=1789319890; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=MCA0mEeYs7WBVVfEtrNNmh1RtFYhSf8Zl2X4qYo/x1U=; b=qnbw7rb1YKKSAmyNQAGIctPcTZWdGR9EQ5v6Bf616lbqryiqDDuxlj/5FFCGIDb7CR FLWPf8N/1Egcbxv8UewZXi5pYzJlYhtFlb4aBr42BVmAMGN4Z491Jkg0E4/6MguYoXYr gaAx3usaSlOm64i5ioAXEB7Zk+y+/oa3XZjUrF/8pTQrR4pGJXgbN3vdq6ohRsh+xnPz 0vRVtTG7RY6B4Z4rITOZgquc1dfhd+WME6kFyp3Y+pK40YBwLV8w8o5+dZ4kdM4s5DG9 Q8Re+Y6M38yJIJaEo7Mfslcm5AdxWngr4UucH2gczBPtYjiJdnX/IWPenMDgj741wc8x zRKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788715090; x=1789319890; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=MCA0mEeYs7WBVVfEtrNNmh1RtFYhSf8Zl2X4qYo/x1U=; b=fPgu9QvmANQX0Kal6srY+ap087Jl85yaO9kfKS9Fiao5CMxGQH6vfXgQph6G6EYS6o iNGKW4s+JvQnr3YbyGeOKc83sh4gFFVqfiYxKX7jDNIFSiTSBlPoNYw7jfjaUofTkfVA uphDRkTCpApAJrmYRsAg9mY6pmzv6p1MvnyYXUA7g+Ba59z4j+kWJKWf5B8IO/VNTaIo luGOmgSLRD+3euTulnIo4Q0AuDmR3nJRo7pfaWMVYnqaFAHl+y0xtUwmm2dR/NCS3Fik sTwRKgK4jz2g/qIBih64ZsaSGiHfFHGKVoMAS9QttbH1DehGw7ETv1Nt8YR1esoQ2iix 6ZRw== X-Gm-Message-State: AFuF++lFSChIVpYmdjF+YxHqZuHA2TxCifjUu8KQhlBz6SkYokU3EomR u4qqiS7WNoYqTfNU0ReIMOgp94AwMNV2S1jG9Sp3i9625ELhxAjJmcAv X-Gm-Gg: AYBFou0KTSf7zAmGrc6Zi+U8/aKURBrIxYzN3+drAHE+cbYRn9IADoAexqjgocxXRt3 meZFb1mNCmuHN12L7zJnqXFcIOFmRr6tw7R5p78saXItAGO5QUELVrTPxMgVvSE2KtByA43j+jo /kcgV96OiNt9vvAEPe1NvU0jNP53deW4U5pMY2hovv87+jns22xcIbHgpFZS+IXJVv4Yzqj7wuq jIIenC3gfQWAeMA+bdjFIWGZfITNOJrKWw6Xmv1hxJGYtoSjaELw4rNrRCztfi+XXi4db3Sbo8p zV22LdQ9UGczvA1VlPAETp/dsxJXPGuDwLaeWL78kwIaUwS3D2Z/wKlb4QP8a49mCadbpSxEEII 4bCXgT9zNl0gcvKgZY+35X7h4NzOhe9cblrraUPkGEIdkZz/QdZg0aVzRVIsTxRamcQwNuniD18 SMV6Ih050UjmWN3K/b/WAGwv6b2H9LVydOWyCOUirRnYU+03c70WL7Kv7UoUXwDNQu0M7cSBU= X-Received: by 2002:a05:690e:1699:b0:66f:ae72:ddec with SMTP id 956f58d0204a3-66fb5abd30emr5574319d50.42.1788715089434; Sun, 06 Sep 2026 10:18:09 -0700 (PDT) Received: from localhost ([2600:1702:7a90:6f9f:8bc4:8aec:108d:7a04]) by smtp.gmail.com with ESMTPSA id 956f58d0204a3-66fb48d6ea5sm6793161d50.7.2026.09.06.10.18.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 06 Sep 2026 10:18:06 -0700 (PDT) From: Matt Turner Date: Sun, 06 Sep 2026 13:18:04 -0400 Subject: [PATCH v4 1/3] tools: port perf ui from GTK 2 to GTK 4 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260906-perf-gtk2-v4-1-97e92ee07214@gmail.com> References: <20260906-perf-gtk2-v4-0-97e92ee07214@gmail.com> In-Reply-To: <20260906-perf-gtk2-v4-0-97e92ee07214@gmail.com> To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark Cc: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, Matt Turner X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=32090; i=mattst88@gmail.com; h=from:subject:message-id; bh=BZym0wR4Aan5tMbnGysaaT/iwspZu2YkmN/kFum26dw=; b=owGbwMvMwCW25rVmCc8sv+mMp9WSGLLmLvCet/xr8aZamwf7tp3h6Ssv1TN+cflAwrl/ApnJh bqXt6Y6dnxkYRDjYpgppsgSt16RZVbbjqU+p6V/wcxhZQIZIi3SwAAELAx8uYl5pUY6Rnqm2oZ6 hkCGjlE8RE6PQSOzuLg0tUg3raDIIS+/JLEkMz+vWC+/IDWvIL1ALy0zrSQjI7+oOBVohF5eaom pq6ObkaGBiaWjhZmThaOpibOzk6GTm6Ojs6uTkaW5iYGzpaOJq6U5AxenAMw1U6cyMhyQvvJQXp 2Jc32dXH4MS49XutChvC3n69ce3eF+qHFx+VNGhgkfSp3fLuNx1+t22xPw6OSKfXP6Zp35YH778 zzZXe+3b2ABAA== X-Developer-Key: i=mattst88@gmail.com; a=openpgp; fpr=3BB639E56F861FA2E86505690FDD682D974CA72A Port straight to GTK 4 rather than the intermediate GTK 3, since GTK 4 is where new development happens and GTK 3 is now old itself. GTK 4 removes GtkContainer, GdkScreen, and the gtk_main()/ gtk_dialog_run() family perf's GTK UI relied on, so this is more than a mechanical rename: containers get per-widget setters (gtk_box_append() and friends), monitor geometry comes from GdkMonitor instead of GdkScreen, and the main and error-dialog loops become explicit GMainLoops, quit from the "close-request" and "response" signals since gtk_main_quit() and gtk_dialog_run() no longer exist. Widgets are visible by default now too, so gtk_widget_show_all()/set_no_show_all() go away. gtk_ui_progress__finish() also skips destroying a progress dialog that was never created, since gtk_window_destroy() asserts on NULL/non-window where the old plain widget destroy tolerated it. Two spots the GTK 2 to GTK 3 port had missed (builtin-annotate.c, ui/gtk/setup.c still using HAVE_GTK2_SUPPORT and gtk_main_quit()) are fixed to match. A few runtime issues come with the new signal-driven loops: the error dialog's nested loop hung if the parent window closed (GTK_DIALOG_DESTROY_WITH_PARENT destroys the dialog without emitting "response") or a signal arrived while the dialog was open; gtk_info_bar_get_content_area() is gone in GTK 4, breaking the build with GTK_INFO_BAR_SUPPORT; the progress dialog's static widget pointers dangled after a manual close; and perf_gtk__error() and the warning functions reused an exhausted va_list when vasprintf() failed. The error loop is tracked in a list rather than a single pointer, since perf_gtk__error() can be called re-entrantly (the dialog isn't modal) and a lone global leaked the outer loop when that happened. stdarg.h and stdio.h are now included explicitly where used instead of relying on transitive includes, which isn't guaranteed on musl. The gtk4-infobar feature check is dropped too: GtkInfoBar has existed unconditionally since GTK 3.10, well before GTK 4's floor, so the check can only ever pass, and on top of that it was failing outright on this system, since gtk_info_bar_new() is deprecated and the check treats deprecation warnings as errors. HAVE_GTK_INFO_BAR_SUPPORT and its statusbar-only fallback go away; the info bar is now built unconditionally. Signed-off-by: Matt Turner --- tools/build/Makefile.feature | 4 +- tools/build/feature/Makefile | 10 +-- tools/build/feature/test-gtk2-infobar.c | 12 --- tools/build/feature/{test-gtk2.c =3D> test-gtk4.c} | 4 +- tools/perf/Documentation/perf-report.txt | 2 +- tools/perf/Makefile | 2 +- tools/perf/Makefile.config | 22 +++--- tools/perf/Makefile.perf | 6 +- tools/perf/builtin-annotate.c | 8 +- tools/perf/builtin-report.c | 8 +- tools/perf/scripts/install-build-deps.sh | 4 +- tools/perf/tests/make | 4 +- tools/perf/ui/gtk/annotate.c | 27 +++---- tools/perf/ui/gtk/browser.c | 56 ++++++++++---- tools/perf/ui/gtk/gtk.h | 13 +--- tools/perf/ui/gtk/hists.c | 33 +++----- tools/perf/ui/gtk/progress.c | 40 +++++++--- tools/perf/ui/gtk/setup.c | 5 +- tools/perf/ui/gtk/util.c | 95 ++++++++++++++------= ---- tools/perf/ui/setup.c | 2 +- 20 files changed, 190 insertions(+), 167 deletions(-) diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 99eb0ea09537..4ec95c35a5c1 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -113,8 +113,7 @@ FEATURE_TESTS_EXTRA :=3D \ compile-x32 \ cplus-demangle \ cxa-demangle \ - gtk2 \ - gtk2-infobar \ + gtk4 \ hello \ babeltrace2-ctf-writer \ libcapstone \ @@ -143,6 +142,7 @@ endif FEATURE_DISPLAY ?=3D \ libdw \ glibc \ + gtk4 \ libelf \ libnuma \ numa_num_possible_cpus \ diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index 7d165018116a..01c48e6ef021 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -11,8 +11,7 @@ FILES=3D \ test-eventfd.bin \ test-fortify-source.bin \ test-glibc.bin \ - test-gtk2.bin \ - test-gtk2-infobar.bin \ + test-gtk4.bin \ test-hello.bin \ test-libbfd.bin \ test-libbfd-threadsafe.bin \ @@ -240,11 +239,8 @@ $(OUTPUT)test-libcpupower.bin: $(OUTPUT)test-libtracefs.bin: $(BUILD) $(shell $(PKG_CONFIG) --cflags libtracefs 2>/dev/null) -ltracefs =20 -$(OUTPUT)test-gtk2.bin: - $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) -Wno= -deprecated-declarations - -$(OUTPUT)test-gtk2-infobar.bin: - $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) +$(OUTPUT)test-gtk4.bin: + $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk4 2>/dev/null) =20 grep-libs =3D $(filter -l%,$(1)) strip-libs =3D $(filter-out -l%,$(1)) diff --git a/tools/build/feature/test-gtk2-infobar.c b/tools/build/feature/= test-gtk2-infobar.c deleted file mode 100644 index b1b716dd5733..000000000000 --- a/tools/build/feature/test-gtk2-infobar.c +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#include -#pragma GCC diagnostic error "-Wstrict-prototypes" - -int main(int argc, char *argv[]) -{ - gtk_init(&argc, &argv); - gtk_info_bar_new(); - - return 0; -} diff --git a/tools/build/feature/test-gtk2.c b/tools/build/feature/test-gtk= 4.c similarity index 76% rename from tools/build/feature/test-gtk2.c rename to tools/build/feature/test-gtk4.c index 2aaf4bfc2055..b9520e7408b9 100644 --- a/tools/build/feature/test-gtk2.c +++ b/tools/build/feature/test-gtk4.c @@ -3,9 +3,9 @@ #include #pragma GCC diagnostic error "-Wstrict-prototypes" =20 -int main(int argc, char *argv[]) +int main(void) { - gtk_init(&argc, &argv); + gtk_init(); =20 return 0; } diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Document= ation/perf-report.txt index 22f87eaa3279..7af9b3f81c06 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -351,7 +351,7 @@ OPTIONS requires a tty, if one is not present, as when piping to other commands, the stdio interface is used. =20 ---gtk:: Use the GTK2 interface. +--gtk:: Use the GTK4 interface. =20 -k:: --vmlinux=3D:: diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 5b713837eede..56014106479a 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -106,7 +106,7 @@ clean: # make -C tools/perf -f tests/make # build-test: - @$(MAKE) SHUF=3D1 -f tests/make REUSE_FEATURES_DUMP=3D1 MK=3DMakefile SET= _PARALLEL=3D1 --no-print-directory tarpkg make_static make_with_gtk2 out + @$(MAKE) SHUF=3D1 -f tests/make REUSE_FEATURES_DUMP=3D1 MK=3DMakefile SET= _PARALLEL=3D1 --no-print-directory tarpkg make_static make_with_gtk4 out =20 build-test-tarball: @$(MAKE) -f tests/make REUSE_FEATURES_DUMP=3D1 MK=3DMakefile SET_PARALLEL= =3D1 --no-print-directory out diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 4d5993da9f94..3e59e2b7eaec 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -774,20 +774,16 @@ ifndef NO_SLANG endif endif =20 -ifdef GTK2 - FLAGS_GTK2=3D$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell $(PKG_CONFIG) --lib= s --cflags gtk+-2.0 2>/dev/null) - $(call feature_check,gtk2) - ifneq ($(feature-gtk2), 1) - $(warning GTK2 not found, disables GTK2 support. Please install gtk2-d= evel or libgtk2.0-dev) - NO_GTK2 :=3D 1 +ifdef GTK4 + FLAGS_GTK4=3D$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell $(PKG_CONFIG) --lib= s --cflags gtk4 2>/dev/null) + $(call feature_check,gtk4) + ifneq ($(feature-gtk4), 1) + $(warning GTK4 not found, disables GTK4 support. Please install gtk4-d= evel or libgtk-4-dev) + NO_GTK4 :=3D 1 else - $(call feature_check,gtk2-infobar) - ifeq ($(feature-gtk2-infobar), 1) - GTK_CFLAGS :=3D -DHAVE_GTK_INFO_BAR_SUPPORT - endif - CFLAGS +=3D -DHAVE_GTK2_SUPPORT - GTK_CFLAGS +=3D $(shell $(PKG_CONFIG) --cflags gtk+-2.0 2>/dev/null) - GTK_LIBS :=3D $(shell $(PKG_CONFIG) --libs gtk+-2.0 2>/dev/null) + CFLAGS +=3D -DHAVE_GTK4_SUPPORT + GTK_CFLAGS +=3D $(shell $(PKG_CONFIG) --cflags gtk4 2>/dev/null) + GTK_LIBS :=3D $(shell $(PKG_CONFIG) --libs gtk4 2>/dev/null) EXTLIBS +=3D -ldl endif endif diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 29cfd44c427f..2438b40eaaec 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -49,7 +49,7 @@ include ../scripts/utilities.mak # # Define NO_SLANG if you do not want TUI support. # -# Define GTK2 if you want GTK+ GUI support. +# Define GTK4 if you want GTK+ GUI support. # # Define NO_DEMANGLE if you do not want C++ symbol demangling. # @@ -473,7 +473,7 @@ ifneq ($(OUTPUT),) CFLAGS +=3D -I$(OUTPUT) endif =20 -ifdef GTK2 +ifdef GTK4 ALL_PROGRAMS +=3D $(OUTPUT)libperf-gtk.so GTK_IN :=3D $(OUTPUT)gtk-in.o endif @@ -811,7 +811,7 @@ check: prepare =20 ### Installation rules =20 -ifdef GTK2 +ifdef GTK4 install-gtk: $(OUTPUT)libperf-gtk.so $(call QUIET_INSTALL, 'GTK UI') \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \ diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 69cb72b2082a..15163e081a8c 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -52,7 +52,7 @@ struct perf_annotate { bool use_tui; #endif bool use_stdio, use_stdio2; -#ifdef HAVE_GTK2_SUPPORT +#ifdef HAVE_GTK4_SUPPORT bool use_gtk; #endif bool skip_missing; @@ -712,7 +712,7 @@ int cmd_annotate(int argc, const char **argv) OPT_BOOLEAN('q', "quiet", &quiet, "do now show any warnings or messages"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), -#ifdef HAVE_GTK2_SUPPORT +#ifdef HAVE_GTK4_SUPPORT OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"), #endif #ifdef HAVE_SLANG_SUPPORT @@ -828,7 +828,7 @@ int cmd_annotate(int argc, const char **argv) if (annotate_check_args() < 0) return -EINVAL; =20 -#ifdef HAVE_GTK2_SUPPORT +#ifdef HAVE_GTK4_SUPPORT if (symbol_conf.show_nr_samples && annotate.use_gtk) { pr_err("--show-nr-samples is not available in --gtk mode at this time\n"= ); return ret; @@ -898,7 +898,7 @@ int cmd_annotate(int argc, const char **argv) else if (annotate.use_tui) use_browser =3D 1; #endif -#ifdef HAVE_GTK2_SUPPORT +#ifdef HAVE_GTK4_SUPPORT else if (annotate.use_gtk) use_browser =3D 2; #endif diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 60d1f166629e..d14384c58466 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -82,7 +82,7 @@ struct report { #ifdef HAVE_SLANG_SUPPORT bool use_tui; #endif -#ifdef HAVE_GTK2_SUPPORT +#ifdef HAVE_GTK4_SUPPORT bool use_gtk; #endif bool use_stdio; @@ -1359,8 +1359,8 @@ int cmd_report(int argc, const char **argv) #ifdef HAVE_SLANG_SUPPORT OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"), #endif -#ifdef HAVE_GTK2_SUPPORT - OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"), +#ifdef HAVE_GTK4_SUPPORT + OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK4 interface"), #endif OPT_BOOLEAN(0, "stdio", &report.use_stdio, "Use the stdio interface"), @@ -1710,7 +1710,7 @@ int cmd_report(int argc, const char **argv) else if (report.use_tui) use_browser =3D 1; #endif -#ifdef HAVE_GTK2_SUPPORT +#ifdef HAVE_GTK4_SUPPORT else if (report.use_gtk) use_browser =3D 2; #endif diff --git a/tools/perf/scripts/install-build-deps.sh b/tools/perf/scripts/= install-build-deps.sh index d003e7fab2be..a601a5260c17 100755 --- a/tools/perf/scripts/install-build-deps.sh +++ b/tools/perf/scripts/install-build-deps.sh @@ -199,8 +199,8 @@ fedora_pkg_for() { # opt-in features, which a default build does not enable: the libbfd # disassembler family (libbfd, libbfd-threadsafe, libbfd-liberty, # disassembler-*, cplus-demangle), only linked on BUILD_NONDISTRO - # builds and deprecated in favor of capstone, GTK2, LIBPERL and - # LIBUNWIND support (ifdef GTK2 / ifdef LIBPERL / LIBUNWIND=3D1), + # builds and deprecated in favor of capstone, GTK4, LIBPERL and + # LIBUNWIND support (ifdef GTK4 / ifdef LIBPERL / LIBUNWIND=3D1), # and CoreSight (ifdef CORESIGHT), are deliberately not mapped. # libaio is not mapped either: its # test uses the POSIX AIO API (aio.h, aio_*, -lrt), provided by diff --git a/tools/perf/tests/make b/tools/perf/tests/make index d2c2f526e1db..202ab5501916 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -95,7 +95,7 @@ make_no_babeltrace2 :=3D NO_BABELTRACE2=3D1 make_with_coresight :=3D CORESIGHT=3D1 make_no_sdt :=3D NO_SDT=3D1 make_no_libpfm4 :=3D NO_LIBPFM4=3D1 -make_with_gtk2 :=3D GTK2=3D1 +make_with_gtk4 :=3D GTK4=3D1 make_refcnt_check :=3D EXTRA_CFLAGS=3D"-DREFCNT_CHECKING=3D1" make_tags :=3D tags make_cscope :=3D cscope @@ -318,7 +318,7 @@ $(run): $(call test,$@) && \ rm -rf $@ $$TMP_DEST || (cat $@ ; false) =20 -make_with_gtk2: +make_with_gtk4: $(call clean) @TMP_DEST=3D$$(mktemp -d); \ cmd=3D"cd $(PERF) && $(MAKE_F) $($@) $(PARALLEL_OPT) $(O_OPT) DESTDIR=3D$= $TMP_DEST"; \ diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 8920e298420a..a9629baa6507 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -161,7 +161,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window,= struct map_symbol *ms, gtk_list_store_set(store, &iter, ANN_COL__LINE, s, -1); } =20 - gtk_container_add(GTK_CONTAINER(window), view); + gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(window), view); =20 list_for_each_entry_safe(pos, n, ¬es->src->source, al.node) { list_del_init(&pos->al.node); @@ -211,34 +211,30 @@ static int symbol__gtk_annotate(struct map_symbol *ms= , struct evsel *evsel, signal(SIGQUIT, perf_gtk__signal); signal(SIGTERM, perf_gtk__signal); =20 - window =3D gtk_window_new(GTK_WINDOW_TOPLEVEL); + window =3D gtk_window_new(); gtk_window_set_title(GTK_WINDOW(window), "perf annotate"); =20 - g_signal_connect(window, "delete_event", gtk_main_quit, NULL); - pgctx =3D perf_gtk__activate_context(window); if (!pgctx) return -1; =20 - vbox =3D gtk_vbox_new(FALSE, 0); + vbox =3D gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); notebook =3D gtk_notebook_new(); pgctx->notebook =3D notebook; =20 - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); + gtk_widget_set_vexpand(notebook, TRUE); + gtk_box_append(GTK_BOX(vbox), notebook); =20 infobar =3D perf_gtk__setup_info_bar(); - if (infobar) { - gtk_box_pack_start(GTK_BOX(vbox), infobar, - FALSE, FALSE, 0); - } + gtk_box_append(GTK_BOX(vbox), infobar); =20 statbar =3D perf_gtk__setup_statusbar(); - gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0); + gtk_box_append(GTK_BOX(vbox), statbar); =20 - gtk_container_add(GTK_CONTAINER(window), vbox); + gtk_window_set_child(GTK_WINDOW(window), vbox); } =20 - scrolled_window =3D gtk_scrolled_window_new(NULL, NULL); + scrolled_window =3D gtk_scrolled_window_new(); tab_label =3D gtk_label_new(sym->name); =20 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), @@ -267,12 +263,11 @@ void perf_gtk__show_annotations(void) return; =20 window =3D pgctx->main_window; - gtk_widget_show_all(window); =20 perf_gtk__resize_window(window); - gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + gtk_widget_set_visible(window, TRUE); =20 - gtk_main(); + perf_gtk__run_main_loop(window); =20 perf_gtk__deactivate_context(&pgctx); } diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index d2dadf3873fb..e1d286945832 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -16,21 +16,53 @@ void perf_gtk__signal(int sig) void perf_gtk__resize_window(GtkWidget *window) { GdkRectangle rect; - GdkScreen *screen; - int monitor; + GdkMonitor *monitor; + GdkDisplay *display; + GListModel *monitors; int height; int width; =20 - screen =3D gtk_widget_get_screen(window); + display =3D gtk_widget_get_display(window); + monitors =3D gdk_display_get_monitors(display); + monitor =3D g_list_model_get_item(monitors, 0); + if (!monitor) { + gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); + return; + } =20 - monitor =3D gdk_screen_get_monitor_at_window(screen, window->window); - - gdk_screen_get_monitor_geometry(screen, monitor, &rect); + gdk_monitor_get_geometry(monitor, &rect); + g_object_unref(monitor); =20 width =3D rect.width * 3 / 4; height =3D rect.height * 3 / 4; =20 - gtk_window_resize(GTK_WINDOW(window), width, height); + gtk_window_set_default_size(GTK_WINDOW(window), width, height); +} + +static GMainLoop *perf_gtk__main_loop; + +void perf_gtk__quit_main_loop(void) +{ + if (perf_gtk__main_loop) + g_main_loop_quit(perf_gtk__main_loop); +} + +static gboolean perf_gtk__close_request(GtkWidget *widget __maybe_unused, + gpointer data __maybe_unused) +{ + perf_gtk__quit_main_loop(); + + return FALSE; +} + +void perf_gtk__run_main_loop(GtkWidget *window) +{ + g_signal_connect(window, "close-request", + G_CALLBACK(perf_gtk__close_request), NULL); + + perf_gtk__main_loop =3D g_main_loop_new(NULL, FALSE); + g_main_loop_run(perf_gtk__main_loop); + g_clear_pointer(&perf_gtk__main_loop, g_main_loop_unref); } =20 const char *perf_gtk__get_percent_color(double percent) @@ -42,23 +74,20 @@ const char *perf_gtk__get_percent_color(double percent) return NULL; } =20 -#ifdef HAVE_GTK_INFO_BAR_SUPPORT GtkWidget *perf_gtk__setup_info_bar(void) { GtkWidget *info_bar; GtkWidget *label; - GtkWidget *content_area; =20 info_bar =3D gtk_info_bar_new(); - gtk_widget_set_no_show_all(info_bar, TRUE); + gtk_widget_set_visible(info_bar, FALSE); =20 label =3D gtk_label_new(""); gtk_widget_show(label); =20 - content_area =3D gtk_info_bar_get_content_area(GTK_INFO_BAR(info_bar)); - gtk_container_add(GTK_CONTAINER(content_area), label); + gtk_info_bar_add_child(GTK_INFO_BAR(info_bar), label); =20 - gtk_info_bar_add_button(GTK_INFO_BAR(info_bar), GTK_STOCK_OK, + gtk_info_bar_add_button(GTK_INFO_BAR(info_bar), "_OK", GTK_RESPONSE_OK); g_signal_connect(info_bar, "response", G_CALLBACK(gtk_widget_hide), NULL); @@ -68,7 +97,6 @@ GtkWidget *perf_gtk__setup_info_bar(void) =20 return info_bar; } -#endif =20 GtkWidget *perf_gtk__setup_statusbar(void) { diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h index a2b497f03fd6..5d263f90fe3a 100644 --- a/tools/perf/ui/gtk/gtk.h +++ b/tools/perf/ui/gtk/gtk.h @@ -13,10 +13,8 @@ struct perf_gtk_context { GtkWidget *main_window; GtkWidget *notebook; =20 -#ifdef HAVE_GTK_INFO_BAR_SUPPORT GtkWidget *info_bar; GtkWidget *message_label; -#endif GtkWidget *statbar; guint statbar_ctx_id; }; @@ -40,17 +38,12 @@ void perf_gtk__init_hpp(void); =20 void perf_gtk__signal(int sig); void perf_gtk__resize_window(GtkWidget *window); +void perf_gtk__run_main_loop(GtkWidget *window); +void perf_gtk__quit_main_loop(void); +void perf_gtk__quit_error_dialog(void); const char *perf_gtk__get_percent_color(double percent); GtkWidget *perf_gtk__setup_statusbar(void); - -#ifdef HAVE_GTK_INFO_BAR_SUPPORT GtkWidget *perf_gtk__setup_info_bar(void); -#else -static inline GtkWidget *perf_gtk__setup_info_bar(void) -{ - return NULL; -} -#endif =20 struct evsel; struct evlist; diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index bae21f336ae6..0b786c5a046b 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -395,11 +395,9 @@ static void perf_gtk__show_hists(GtkWidget *window, st= ruct hists *hists, } } =20 - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE); - g_signal_connect(view, "row-activated", G_CALLBACK(on_row_activated), NULL); - gtk_container_add(GTK_CONTAINER(window), view); + gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(window), view); } =20 static void perf_gtk__add_hierarchy_entries(struct hists *hists, @@ -583,11 +581,9 @@ static void perf_gtk__show_hierarchy(GtkWidget *window= , struct hists *hists, perf_gtk__add_hierarchy_entries(hists, &hists->entries, store, NULL, &hpp, min_pcnt); =20 - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE); - g_signal_connect(view, "row-activated", G_CALLBACK(on_row_activated), NULL); - gtk_container_add(GTK_CONTAINER(window), view); + gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(window), view); } =20 int evlist__gtk_browse_hists(struct evlist *evlist, const char *help, @@ -606,30 +602,28 @@ int evlist__gtk_browse_hists(struct evlist *evlist, c= onst char *help, signal(SIGQUIT, perf_gtk__signal); signal(SIGTERM, perf_gtk__signal); =20 - window =3D gtk_window_new(GTK_WINDOW_TOPLEVEL); + window =3D gtk_window_new(); =20 gtk_window_set_title(GTK_WINDOW(window), "perf report"); =20 - g_signal_connect(window, "delete_event", gtk_main_quit, NULL); - pgctx =3D perf_gtk__activate_context(window); if (!pgctx) return -1; =20 - vbox =3D gtk_vbox_new(FALSE, 0); + vbox =3D gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); =20 notebook =3D gtk_notebook_new(); =20 - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); + gtk_widget_set_vexpand(notebook, TRUE); + gtk_box_append(GTK_BOX(vbox), notebook); =20 info_bar =3D perf_gtk__setup_info_bar(); - if (info_bar) - gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0); + gtk_box_append(GTK_BOX(vbox), info_bar); =20 statbar =3D perf_gtk__setup_statusbar(); - gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0); + gtk_box_append(GTK_BOX(vbox), statbar); =20 - gtk_container_add(GTK_CONTAINER(window), vbox); + gtk_window_set_child(GTK_WINDOW(window), vbox); =20 evlist__for_each_entry(evlist, pos) { struct hists *hists =3D evsel__hists(pos); @@ -649,7 +643,7 @@ int evlist__gtk_browse_hists(struct evlist *evlist, con= st char *help, } } =20 - scrolled_window =3D gtk_scrolled_window_new(NULL, NULL); + scrolled_window =3D gtk_scrolled_window_new(); =20 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, @@ -665,15 +659,12 @@ int evlist__gtk_browse_hists(struct evlist *evlist, c= onst char *help, gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_la= bel); } =20 - gtk_widget_show_all(window); - perf_gtk__resize_window(window); - - gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + gtk_widget_set_visible(window, TRUE); =20 ui_helpline__push(help); =20 - gtk_main(); + perf_gtk__run_main_loop(window); =20 perf_gtk__deactivate_context(&pgctx); =20 diff --git a/tools/perf/ui/gtk/progress.c b/tools/perf/ui/gtk/progress.c index eea6fcde518a..770f9251b54b 100644 --- a/tools/perf/ui/gtk/progress.c +++ b/tools/perf/ui/gtk/progress.c @@ -1,49 +1,65 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include =20 #include "gtk.h" #include "../progress.h" +#include =20 static GtkWidget *dialog; static GtkWidget *progress; =20 +static void gtk_ui_progress__destroyed(GtkWidget *widget __maybe_unused, + gpointer data __maybe_unused) +{ + dialog =3D NULL; + progress =3D NULL; +} + static void gtk_ui_progress__update(struct ui_progress *p) { double fraction =3D p->total ? 1.0 * p->curr / p->total : 0.0; char buf[1024]; =20 if (dialog =3D=3D NULL) { - GtkWidget *vbox =3D gtk_vbox_new(TRUE, 5); + GtkWidget *vbox =3D gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); GtkWidget *label =3D gtk_label_new(p->title); =20 - dialog =3D gtk_window_new(GTK_WINDOW_TOPLEVEL); + dialog =3D gtk_window_new(); progress =3D gtk_progress_bar_new(); =20 - gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 3); - gtk_box_pack_start(GTK_BOX(vbox), progress, TRUE, TRUE, 3); + gtk_widget_set_vexpand(label, TRUE); + gtk_box_append(GTK_BOX(vbox), label); + gtk_widget_set_vexpand(progress, TRUE); + gtk_box_append(GTK_BOX(vbox), progress); =20 - gtk_container_add(GTK_CONTAINER(dialog), vbox); + gtk_window_set_child(GTK_WINDOW(dialog), vbox); + + g_signal_connect(dialog, "destroy", + G_CALLBACK(gtk_ui_progress__destroyed), NULL); =20 gtk_window_set_title(GTK_WINDOW(dialog), "perf"); - gtk_window_resize(GTK_WINDOW(dialog), 300, 80); - gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); + gtk_window_set_default_size(GTK_WINDOW(dialog), 300, 80); =20 - gtk_widget_show_all(dialog); + gtk_widget_set_visible(dialog, TRUE); } =20 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction); snprintf(buf, sizeof(buf), "%"PRIu64" / %"PRIu64, p->curr, p->total); gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), buf); =20 - /* we didn't call gtk_main yet, so do it manually */ - while (gtk_events_pending()) - gtk_main_iteration(); + /* we didn't start a main loop yet, so pump events manually */ + while (g_main_context_pending(NULL)) + g_main_context_iteration(NULL, FALSE); } =20 static void gtk_ui_progress__finish(void) { + if (dialog =3D=3D NULL) + return; + /* this will also destroy all of its children */ - gtk_widget_destroy(dialog); + gtk_window_destroy(GTK_WINDOW(dialog)); =20 dialog =3D NULL; } diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c index f5eee4d66873..9b44f3719747 100644 --- a/tools/perf/ui/gtk/setup.c +++ b/tools/perf/ui/gtk/setup.c @@ -12,7 +12,7 @@ int perf_gtk__init(void) gtk_ui_progress__init(); perf_gtk__init_hpp(); =20 - return gtk_init_check(NULL, NULL) ? 0 : -1; + return gtk_init_check() ? 0 : -1; } =20 void perf_gtk__exit(bool wait_for_ok __maybe_unused) @@ -20,5 +20,6 @@ void perf_gtk__exit(bool wait_for_ok __maybe_unused) if (!perf_gtk__is_active_context(pgctx)) return; perf_error__unregister(&perf_gtk_eops); - gtk_main_quit(); + perf_gtk__quit_error_dialog(); + perf_gtk__quit_main_loop(); } diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c index c47f5c387838..8a922851257e 100644 --- a/tools/perf/ui/gtk/util.c +++ b/tools/perf/ui/gtk/util.c @@ -2,8 +2,10 @@ #include "../util.h" #include "gtk.h" =20 +#include +#include #include -#include +#include #include =20 struct perf_gtk_context *pgctx; @@ -28,43 +30,92 @@ int perf_gtk__deactivate_context(struct perf_gtk_contex= t **ctx) return 0; } =20 +/* + * perf_gtk__error() can be called re-entrantly, since the dialog isn't + * modal and its nested loop still pumps events for the main window. + * Track every currently running loop instead of a single pointer, so a + * nested call can't clobber an outer call's loop and leak it. + */ +static GSList *perf_gtk__error_loops; + +static void perf_gtk__quit_loop(gpointer data, gpointer user_data __maybe_= unused) +{ + g_main_loop_quit(data); +} + +void perf_gtk__quit_error_dialog(void) +{ + g_slist_foreach(perf_gtk__error_loops, perf_gtk__quit_loop, NULL); +} + +static void perf_gtk__dialog_response(GtkDialog *dialog, + gint response_id __maybe_unused, + gpointer data __maybe_unused) +{ + gtk_window_destroy(GTK_WINDOW(dialog)); +} + static int perf_gtk__error(const char *format, va_list args) { char *msg; GtkWidget *dialog; + GMainLoop *loop; + va_list args_copy; =20 + va_copy(args_copy, args); if (!perf_gtk__is_active_context(pgctx) || - vasprintf(&msg, format, args) < 0) { + vasprintf(&msg, format, args_copy) < 0) { + va_end(args_copy); fprintf(stderr, "Error:\n"); vfprintf(stderr, format, args); fprintf(stderr, "\n"); return -1; } + va_end(args_copy); =20 dialog =3D gtk_message_dialog_new_with_markup(GTK_WINDOW(pgctx->main_wind= ow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Error\n\n%s", msg); - gtk_dialog_run(GTK_DIALOG(dialog)); =20 - gtk_widget_destroy(dialog); + /* + * "response" only fires when a button is clicked; DESTROY_WITH_PARENT + * destroys the dialog directly without it. Quit from "destroy" + * instead, which fires either way, so the nested loop below can't + * outlive the dialog and hang. + */ + loop =3D g_main_loop_new(NULL, FALSE); + perf_gtk__error_loops =3D g_slist_prepend(perf_gtk__error_loops, loop); + g_signal_connect(dialog, "response", + G_CALLBACK(perf_gtk__dialog_response), NULL); + g_signal_connect_swapped(dialog, "destroy", + G_CALLBACK(g_main_loop_quit), loop); + + gtk_widget_set_visible(dialog, TRUE); + g_main_loop_run(loop); + perf_gtk__error_loops =3D g_slist_remove(perf_gtk__error_loops, loop); + g_main_loop_unref(loop); + free(msg); return 0; } =20 -#ifdef HAVE_GTK_INFO_BAR_SUPPORT static int perf_gtk__warning_info_bar(const char *format, va_list args) { char *msg; + va_list args_copy; =20 + va_copy(args_copy, args); if (!perf_gtk__is_active_context(pgctx) || - vasprintf(&msg, format, args) < 0) { + vasprintf(&msg, format, args_copy) < 0) { + va_end(args_copy); fprintf(stderr, "Warning:\n"); vfprintf(stderr, format, args); fprintf(stderr, "\n"); return -1; } + va_end(args_copy); =20 gtk_label_set_text(GTK_LABEL(pgctx->message_label), msg); gtk_info_bar_set_message_type(GTK_INFO_BAR(pgctx->info_bar), @@ -74,40 +125,8 @@ static int perf_gtk__warning_info_bar(const char *forma= t, va_list args) free(msg); return 0; } -#else -static int perf_gtk__warning_statusbar(const char *format, va_list args) -{ - char *msg, *p; - - if (!perf_gtk__is_active_context(pgctx) || - vasprintf(&msg, format, args) < 0) { - fprintf(stderr, "Warning:\n"); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - return -1; - } - - gtk_statusbar_pop(GTK_STATUSBAR(pgctx->statbar), - pgctx->statbar_ctx_id); - - /* Only first line can be displayed */ - p =3D strchr(msg, '\n'); - if (p) - *p =3D '\0'; - - gtk_statusbar_push(GTK_STATUSBAR(pgctx->statbar), - pgctx->statbar_ctx_id, msg); - - free(msg); - return 0; -} -#endif =20 struct perf_error_ops perf_gtk_eops =3D { .error =3D perf_gtk__error, -#ifdef HAVE_GTK_INFO_BAR_SUPPORT .warning =3D perf_gtk__warning_info_bar, -#else - .warning =3D perf_gtk__warning_statusbar, -#endif }; diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c index ff800047e697..d887346c7a63 100644 --- a/tools/perf/ui/setup.c +++ b/tools/perf/ui/setup.c @@ -14,7 +14,7 @@ int use_browser =3D -1; =20 #define PERF_GTK_DSO "libperf-gtk.so" =20 -#ifdef HAVE_GTK2_SUPPORT +#ifdef HAVE_GTK4_SUPPORT =20 static int setup_gtk_browser(void) { --=20 2.54.0 From nobody Sat Sep 26 01:39:34 2026 Received: from mail-yw1-f182.google.com (mail-yw1-f182.google.com [209.85.128.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 09551355F4E for ; Sun, 6 Sep 2026 17:18:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788715094; cv=none; b=mbMKaur5jlo2J6aSqVPNzGNetrFjNwwGPA9DN4MT+PDJDrIbhORjg3iEjMTbvHRTkLwnl/PP0ubD4X70O7DGm//4nO5xg0QNC1+rRN7wVSfJFQc/LRS+e6fbGTWZHPCz6V7BkPiWZHG7gEsSdXTNBQ/aNgdNAWdUd6/xVhp137s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788715094; c=relaxed/simple; bh=8CvFHtfn4Ljqx5Fa6L2b6SNfX914djxML7DsfBsaOO4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TV0tNKqM3TeT+nhoKbue4lN5U/y+gQA/qX1Hfy4sBCmxRgmgWdEXN82LjPgdOlWBLEtN9OAwpfbBzwP+PJmkXElOPEQl1/ML76VWGbv0CM4Eg9e+KpsVmChh5yzwjW/6d8pKKL3Yjih+s3O5DQz9mF0mBHtT7wn0wPbW5cGKs84= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=FJ8HSNUn; arc=none smtp.client-ip=209.85.128.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FJ8HSNUn" Received: by mail-yw1-f182.google.com with SMTP id 00721157ae682-836c8bde2dcso9772887b3.0 for ; Sun, 06 Sep 2026 10:18:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788715091; x=1789319891; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=e9O0Uei0AmYGxnrMfKSWfJBNUDOym4vtr5Ws3/LSEZc=; b=FJ8HSNUnHyZwKW7jb7fiThMpJPU5z4rzBQTJPq2vKn1bbOlCRSWCinjLZ/7NfYLeyU Cks0iDQipNobaTfzx7xcsQ/g0I+B/3dvnTizzNVWthJzyegwNEz/ni3kRt0FPY7caIns vBceNda2B20QHFYmIROPFwxaBr5YwZOnIrSu3D/iyXjjyIagkvOP8jPSAF5o7067epCW d2aVqC2z0v1mkKLQKLRKVTk8pSLP4piFn55YrVP6uMf5s9yDSdPqOD59HVIq/i/Zy6Vr 67UfmUElqsDCF9dwSvmTi2l42tX9KZz7Ta9OpTxD2Gyo7K4AyRLpG32z+d5laTQnDObf 5Iog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788715091; x=1789319891; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=e9O0Uei0AmYGxnrMfKSWfJBNUDOym4vtr5Ws3/LSEZc=; b=pOF7zzixiPLrBkK8WAs/w9G2Zgu7ngq8Hk0aMtDjSr9vQtBi4c79SJoIgPnDwuFNSq WuQ95r2m6qyJrVYOuBCd3/7Sj3kZdDSYSkLGeK5g7xw/h/2OV1on20mQKjx1IB7em6O4 EQDKHrjBK5CEnhmu1Pb55XHhTMqiML6xv8+ipHSMHc9h6YnF+Xt/R4C+90prM763eeky 9OOd5jKxRxgsWZnwAbUd4WzK/6o1mDIbGPs+F2Rhnu73ooQVp8+WrxOXBzN+p5IFHKLe vX96nHzMAVGOYGmHKrLu8S0h07gMd6YqtVSesEEeVPden4v4CpiSOFs60Na9gXWKHQUw OPSQ== X-Gm-Message-State: AFuF++mcpahKm5HWoddy7usu8Z7sjGd1Sps37+8YC0u0o+X1iZnyOfrh 1EHz1doPe3EhSVH1Sl6YC1aop7q7y/AC3JFpadzofoHdHrBPgfo9qRVY X-Gm-Gg: AYBFou34OsSSqB+nGvuDtuuXlww5ZQR+fJWg5ZlBWceetrZYdRG0LEJrFcDs/wkz9p7 nGsntnNp8sGrVQrPe4h+s1IP4Snk/9fzXGeIysXF9ZYtrLDWKSCh7BODMfAUA4JHnziEYqrW/qO MV4Fvm2rIaopJxq4JuQ953HdwBSAD57IuPbW4GsEpvZxhvv6p372JAeSYRfQDFrZH+5yTgjJUpV CiaLm3qNXtVuLa2O55UiGJ7zRau8ywNbxinkPqQyVcd5VQxSp3RpljaYqnDgFIKwADLjBPJJBJo e7Z6cIuPdoZQ6gBn+JguxVLJ1hMkGLt4k9T6OOWXWZcsgDaORkSoK4Z37KnS5jNp7auP4HGA3wq kfG/qzwEIsQ/HHtexeNj4thwC32xTTFu0z07y3s269CRGeczQt6bnB4v2jpAEgFYEPV2ZiJXlJW z+ou2IKkmEMVWkqXKitXDvoIVuoyk1Immeba4/fIuBoCgyog7Nj7j8a49BQq5MQnil1Lw67V4= X-Received: by 2002:a05:690c:e3ec:b0:876:6206:512f with SMTP id 00721157ae682-876620652ffmr13759577b3.43.1788715091362; Sun, 06 Sep 2026 10:18:11 -0700 (PDT) Received: from localhost ([2600:1702:7a90:6f9f:8bc4:8aec:108d:7a04]) by smtp.gmail.com with ESMTPSA id 00721157ae682-8714af5581bsm57889107b3.36.2026.09.06.10.18.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 06 Sep 2026 10:18:10 -0700 (PDT) From: Matt Turner Date: Sun, 06 Sep 2026 13:18:05 -0400 Subject: [PATCH v4 2/3] perf tools: make the GTK4 report browser actually loadable at runtime Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260906-perf-gtk2-v4-2-97e92ee07214@gmail.com> References: <20260906-perf-gtk2-v4-0-97e92ee07214@gmail.com> In-Reply-To: <20260906-perf-gtk2-v4-0-97e92ee07214@gmail.com> To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark Cc: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, Matt Turner X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=4031; i=mattst88@gmail.com; h=from:subject:message-id; bh=8CvFHtfn4Ljqx5Fa6L2b6SNfX914djxML7DsfBsaOO4=; b=owGbwMvMwCW25rVmCc8sv+mMp9WSGLLmLvCZzJnAdcb9+Yu1on22p52udcRl5Pz9FffIcvsVu ZU7PsoZdnxkYRDjYpgppsgSt16RZVbbjqU+p6V/wcxhZQIZIi3SwAAELAx8uYl5pUY6Rnqm2oZ6 hkCGjlE8RE6PQSOzuLg0tUg3raDIIS+/JLEkMz+vWC+/IDWvIL1ALy0zrSQjI7+oOBVohF5eaom pq6ObkaGBiaWjhZmThaOpibOzk6GTm6Ojs6uTkaW5iYGzpaOJq6U5AxenAMw1kzoZGS6wF50pXb pduGe18uuyx5v7Hxx5YJO840my1U+DzTMUP59iZNi7nk06T06l83kze9/CCKOdUkvzRFkmap+xt vn99dfTFg4A X-Developer-Key: i=mattst88@gmail.com; a=openpgp; fpr=3BB639E56F861FA2E86505690FDD682D974CA72A perf report --gtk dlopen()s libperf-gtk.so and expects it to resolve symbols back against the running perf binary (callchain_param, symbol_conf, evsel__name, and friends all live in perf itself, not in the plugin). Two things stood in the way of that after the GTK 2 to GTK 4 port: perf never passed -rdynamic, so none of its own symbols were in its dynamic symbol table for a dlopen()ed plugin to find at all. Add -rdynamic to LDFLAGS when GTK4 support is enabled. annotated_source__hist_entry() was a static inline in annotate.h, so ui/gtk/annotate.c calling it pulled hashmap__find()'s expansion, hashmap_find(), directly into libperf-gtk.so as an undefined symbol. The only hashmap_find perf links against in the common case is libbpf's internal one (tools/lib/bpf/hashmap.c), which libbpf compiles with -fvisibility=3Dhidden; a hidden symbol can never be exported to a dlopen()ed plugin no matter what LDFLAGS perf itself gets. Move annotated_source__hist_entry() out of the header and into annotate.c, as an ordinary exported function, so the plugin depends on it the same way it already depends on evsel__group_desc() and friends, instead of reaching for hashmap_find directly. With both fixes, a default 'make GTK4=3D1' build (libbpf statically linked, as usual) can dlopen() libperf-gtk.so and open the report browser without needing NO_LIBBPF=3D1 or manual LDFLAGS. Verified with perf report --gtk against a real perf.data on an actual GTK4 desktop session. Signed-off-by: Matt Turner --- tools/perf/Makefile.config | 5 +++++ tools/perf/util/annotate.c | 11 +++++++++++ tools/perf/util/annotate.h | 12 ++---------- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 3e59e2b7eaec..4ee7393a39f9 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -785,6 +785,11 @@ ifdef GTK4 GTK_CFLAGS +=3D $(shell $(PKG_CONFIG) --cflags gtk4 2>/dev/null) GTK_LIBS :=3D $(shell $(PKG_CONFIG) --libs gtk4 2>/dev/null) EXTLIBS +=3D -ldl + # libperf-gtk.so is dlopen()ed at runtime and calls back into + # symbols defined in the perf binary itself (callchain_param, + # symbol_conf, evsel__name, ...): perf needs to export those + # dynamically for the plugin to resolve them. + LDFLAGS +=3D -rdynamic endif endif =20 diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index df70e95a8470..123b6d5fcea7 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -145,6 +145,17 @@ static int annotated_source__alloc_histograms(struct a= nnotated_source *src, return src->histograms ? 0 : -1; } =20 +struct sym_hist_entry * +annotated_source__hist_entry(struct annotated_source *src, const struct ev= sel *evsel, u64 offset) +{ + struct sym_hist_entry *entry; + long key =3D offset << 16 | evsel->core.idx; + + if (!hashmap__find(src->samples, key, &entry)) + return NULL; + return entry; +} + void symbol__annotate_zero_histograms(struct symbol *sym) { struct annotation *notes =3D symbol__annotation(sym); diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index fa08d09b80f7..40038a3779d4 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -406,16 +406,8 @@ static inline struct sym_hist *annotation__histogram(s= truct annotation *notes, return annotated_source__histogram(notes->src, evsel); } =20 -static inline struct sym_hist_entry * -annotated_source__hist_entry(struct annotated_source *src, const struct ev= sel *evsel, u64 offset) -{ - struct sym_hist_entry *entry; - long key =3D offset << 16 | evsel->core.idx; - - if (!hashmap__find(src->samples, key, &entry)) - return NULL; - return entry; -} +struct sym_hist_entry * +annotated_source__hist_entry(struct annotated_source *src, const struct ev= sel *evsel, u64 offset); =20 static inline struct annotation *symbol__annotation(struct symbol *sym) { --=20 2.54.0 From nobody Sat Sep 26 01:39:34 2026 Received: from mail-yw1-f172.google.com (mail-yw1-f172.google.com [209.85.128.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 769083BE15F for ; Sun, 6 Sep 2026 17:18:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788715097; cv=none; b=ozQJYaJarZN/qrqEpQhiGXjcaVducYDmCKGltzH+rfutfytntbz2I1oxif7E0gqgTC78+Rj/AvpZPZ4vD+Wfi2ugV9sMYWRtMmmTMjWwcshv3yfTMboIxyTdpZWd0bFzSpppps2FOevOZBQ7sE6QVxlzJFi+MWWChH5WAvYZDI4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788715097; c=relaxed/simple; bh=WYWkloWX0WwYIbfuRU0AbifbyJ2iXxd78Hzjdu5xb60=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ooW0xkcs/iSz3uBJtq8jFajLHg12P0otzxWfFkQPOSlNHUTsjLH/K+PXLd0iVJ/FvM6Itmq8zpws73yx6s7glyJMjpqPQAWqSgkkMJc1z/98cdNyoYAlSGUHzigk1dCuIF6i7VGl75Z6DlK7T6L9lSewHSXeBPpDTr+BlRVOUYc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=KJ3RKGop; arc=none smtp.client-ip=209.85.128.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KJ3RKGop" Received: by mail-yw1-f172.google.com with SMTP id 00721157ae682-867a943b149so42803657b3.1 for ; Sun, 06 Sep 2026 10:18:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788715093; x=1789319893; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=t5Xptp4H+rxzUUCx4qt8Wtg7L4/4Oif3JrXMZT5ooQM=; b=KJ3RKGopVD+MUwJKsDfjsTr13qI4M9luSyJs4hA133gHsuBvrnUs0/+hrDcVadH03l nuFjLQF257l2gCXDcaeW/1MhQBbYFg+PyyxMmNjGUzf+pEnSMe+aYJVXAFO6d5Wx1kDn 4129G0IxXCiqeIxTZIi3H6qxYwK3xpt92O64MvOHcrtSEwvanLI1KRyFdbWY11PT6kM/ k178iCvIKm3Z7KsP399yzw4UXUQmtv3B1S6J5kUrIgYUTlyr0EDbaocABXkp8gzqiyFM 24bv/Jw0lYGkXWjK1JVl4XdMCNBkrHz4tavFE05/sXTsIQZDjO3ObCWvkNwwqD9Sx7y5 SLRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788715093; x=1789319893; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=t5Xptp4H+rxzUUCx4qt8Wtg7L4/4Oif3JrXMZT5ooQM=; b=Adtk3jHuJyA6gpnvIEqsYOjx7CNI9zATWTt/nPvpQ8r+tVH4mZVZbbzJQr0FszYO/1 V7Kz+lz0vzHRLTUzDrP6/u3lJUIG1XXTd/oOE0enOqO1RNG0t/6VFHb8d+sY/XiR0GOc ERb/gmjaeHmSaQsVUajDrMHFVvTJVQHj2xjH3XHbCjDlmg/02TXw5ndg2aJZ6myrH6gA rpYzj9747aO2zJWmp1Tuu2Qjrwb7iytFDGhEeS40uWA2vCqazLiJthYi9+05jgaP8PRq usDiybLRuum7+56ppzRaDYEMZccfSjYBIx6p/qbf+BqY3UN4LQCXg3d3wV28rWoreu5J db3w== X-Gm-Message-State: AFuF++kqooIjatu3Q1FND2oyzDhQovRiGt1CBOAAWhKK7xqrUDS756NV VHneHGa5F6tcPgj8bDetpOmgEZhouECwejv9OhtDzsoxJSVKy/ZDwH5W X-Gm-Gg: AYBFou3r5oq6adcm59m9ZLBWEwG01mYKKUicmKSjFzvH48IYVPcBnDgTw8z4c24P/GG LfbvpbgF04Iu6n59au4kuDI6KJ8dJAKIKDDuc7zDYMDXJyXOKukGc4rEELGR3GBgjVC6hwroXb1 xR7V3q4a7MgOSju+hUP12ROwl/L86VPnHpaWPMGfRAVP5n1IGOudbZ0sZEvd/KTwmsk4Pyix3LQ YGgsYcwGd8rJJoPVzb762HfLpim4dDXM65T7c+A/HlDVmChqN4zsik8v8huX3jw0XsHzk/EfxIi n+bEuRA48aTjjhb7UTcOQwuPwgCFyYf9CyAA7+h3uJiCcbZOLCXPtsCKDbtVGlQxoF2zvT6Szjv KieKsTyVBF93A6xHEhYbCKt7CWHGYU9G773mFj2xsqp+4Sy92FvQWaEhL8htygu9vTJqtkLAhM4 oc1khgjOKSDOi/PS/VNQiPPOXdwJi5FHWwrW+Bb66WZfdsjE5vqJXgb+YrxRxSOQ== X-Received: by 2002:a05:690c:1a:b0:873:5bd1:98b1 with SMTP id 00721157ae682-8735bd19fa2mr41605437b3.35.1788715093078; Sun, 06 Sep 2026 10:18:13 -0700 (PDT) Received: from localhost ([2600:1702:7a90:6f9f:8bc4:8aec:108d:7a04]) by smtp.gmail.com with ESMTPSA id 00721157ae682-8714b62bc77sm58248267b3.39.2026.09.06.10.18.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 06 Sep 2026 10:18:12 -0700 (PDT) From: Matt Turner Date: Sun, 06 Sep 2026 13:18:06 -0400 Subject: [PATCH v4 3/3] perf tools: fix GTK4 leftover show/hide calls and error-loop list race Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260906-perf-gtk2-v4-3-97e92ee07214@gmail.com> References: <20260906-perf-gtk2-v4-0-97e92ee07214@gmail.com> In-Reply-To: <20260906-perf-gtk2-v4-0-97e92ee07214@gmail.com> To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark Cc: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, Matt Turner X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=4571; i=mattst88@gmail.com; h=from:subject:message-id; bh=WYWkloWX0WwYIbfuRU0AbifbyJ2iXxd78Hzjdu5xb60=; b=owGbwMvMwCW25rVmCc8sv+mMp9WSGLLmLvBp23LZQib47aP9Z933OftXl5u5Vk3rqTmRt1s4O uXu2vDTHR9ZGMS4GGaKKbLErVdkmdW2Y6nPaelfMHNYmUCGSIs0MAABCwNfbmJeqZGOkZ6ptqGe IZChYxQPkdNj0MgsLi5NLdJNKyhyyMsvSSzJzM8r1ssvSM0rSC/QS8tMK8nIyC8qTgUaoZeXWmL q6uhmZGhgYuloYeZk4Whq4uzsZOjk5ujo7OpkZGluYuBs6WjiamnOwMUpAHNNaQzDT8Yrs272TQ nT9+yyKnRWrdvCznxQI/uZlsq9oFKuTxwaLQx/xfYtbLF/eCdudyTzGbb6vdqBhdMSvaRbFe+W/ 97CveAvFwA= X-Developer-Key: i=mattst88@gmail.com; a=openpgp; fpr=3BB639E56F861FA2E86505690FDD682D974CA72A Sashiko AI review of the GTK2-to-GTK4 port flagged two real issues: - gtk_widget_show()/gtk_widget_hide() were removed in GTK4 but three call sites were missed during the port. Replace with gtk_widget_set_visible(), adding a small wrapper for the info-bar "response" signal callback since gtk_widget_hide() no longer exists to pass directly. - perf_gtk__error_loops is updated with g_slist_prepend()/ g_slist_remove() in perf_gtk__error(), but perf_gtk__quit_error_dialog() walks the same list from a signal handler (perf_gtk__signal() -> perf_gtk__exit()) that can fire mid-update, corrupting the list. Block the relevant signals around the two list updates. --- tools/perf/ui/gtk/browser.c | 10 ++++++++-- tools/perf/ui/gtk/util.c | 27 ++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index e1d286945832..40a413787192 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -74,6 +74,12 @@ const char *perf_gtk__get_percent_color(double percent) return NULL; } =20 +static void perf_gtk__hide_widget(GtkWidget *widget, gint response_id __ma= ybe_unused, + gpointer data __maybe_unused) +{ + gtk_widget_set_visible(widget, FALSE); +} + GtkWidget *perf_gtk__setup_info_bar(void) { GtkWidget *info_bar; @@ -83,14 +89,14 @@ GtkWidget *perf_gtk__setup_info_bar(void) gtk_widget_set_visible(info_bar, FALSE); =20 label =3D gtk_label_new(""); - gtk_widget_show(label); + gtk_widget_set_visible(label, TRUE); =20 gtk_info_bar_add_child(GTK_INFO_BAR(info_bar), label); =20 gtk_info_bar_add_button(GTK_INFO_BAR(info_bar), "_OK", GTK_RESPONSE_OK); g_signal_connect(info_bar, "response", - G_CALLBACK(gtk_widget_hide), NULL); + G_CALLBACK(perf_gtk__hide_widget), NULL); =20 pgctx->info_bar =3D info_bar; pgctx->message_label =3D label; diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c index 8a922851257e..f1dbd96e2370 100644 --- a/tools/perf/ui/gtk/util.c +++ b/tools/perf/ui/gtk/util.c @@ -2,6 +2,7 @@ #include "../util.h" #include "gtk.h" =20 +#include #include #include #include @@ -48,6 +49,25 @@ void perf_gtk__quit_error_dialog(void) g_slist_foreach(perf_gtk__error_loops, perf_gtk__quit_loop, NULL); } =20 +/* + * perf_gtk__signal() runs perf_gtk__quit_error_dialog() from a signal + * handler, which can preempt perf_gtk__error() while it is updating + * perf_gtk__error_loops below. Block those signals around the update so + * the list is never traversed half-modified. + */ +static void perf_gtk__block_exit_signals(sigset_t *old_set) +{ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGSEGV); + sigaddset(&set, SIGFPE); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGQUIT); + sigaddset(&set, SIGTERM); + sigprocmask(SIG_BLOCK, &set, old_set); +} + static void perf_gtk__dialog_response(GtkDialog *dialog, gint response_id __maybe_unused, gpointer data __maybe_unused) @@ -61,6 +81,7 @@ static int perf_gtk__error(const char *format, va_list ar= gs) GtkWidget *dialog; GMainLoop *loop; va_list args_copy; + sigset_t old_set; =20 va_copy(args_copy, args); if (!perf_gtk__is_active_context(pgctx) || @@ -86,7 +107,9 @@ static int perf_gtk__error(const char *format, va_list a= rgs) * outlive the dialog and hang. */ loop =3D g_main_loop_new(NULL, FALSE); + perf_gtk__block_exit_signals(&old_set); perf_gtk__error_loops =3D g_slist_prepend(perf_gtk__error_loops, loop); + sigprocmask(SIG_SETMASK, &old_set, NULL); g_signal_connect(dialog, "response", G_CALLBACK(perf_gtk__dialog_response), NULL); g_signal_connect_swapped(dialog, "destroy", @@ -94,7 +117,9 @@ static int perf_gtk__error(const char *format, va_list a= rgs) =20 gtk_widget_set_visible(dialog, TRUE); g_main_loop_run(loop); + perf_gtk__block_exit_signals(&old_set); perf_gtk__error_loops =3D g_slist_remove(perf_gtk__error_loops, loop); + sigprocmask(SIG_SETMASK, &old_set, NULL); g_main_loop_unref(loop); =20 free(msg); @@ -120,7 +145,7 @@ static int perf_gtk__warning_info_bar(const char *forma= t, va_list args) gtk_label_set_text(GTK_LABEL(pgctx->message_label), msg); gtk_info_bar_set_message_type(GTK_INFO_BAR(pgctx->info_bar), GTK_MESSAGE_WARNING); - gtk_widget_show(pgctx->info_bar); + gtk_widget_set_visible(pgctx->info_bar, TRUE); =20 free(msg); return 0; --=20 2.54.0