From a7665377ae5086e724fc66a838232bf8ee829d55 Mon Sep 17 00:00:00 2001 From: Achill Gilgenast Date: Tue, 2 Jun 2026 21:09:09 +0200 Subject: [PATCH] systemd/phosh: backport patch for extending app startup timer Helps UX on slower devices like the PinePhone a lot, let's backport it. This was suggested by upstream[1]. [1]: https://gitlab.gnome.org/World/Phosh/phosh/-/merge_requests/1915#note_2778701 See: https://gitlab.alpinelinux.org/alpine/aports/-/merge_requests/103390 Part-of: --- extra-repos/systemd/phosh/APKBUILD | 9 +- .../phosh/extend-timeout-with-pid.patch | 205 ++++++++++++++++++ .../systemd/phosh/use-after-free-fix.patch | 54 +++++ 3 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 extra-repos/systemd/phosh/extend-timeout-with-pid.patch create mode 100644 extra-repos/systemd/phosh/use-after-free-fix.patch diff --git a/extra-repos/systemd/phosh/APKBUILD b/extra-repos/systemd/phosh/APKBUILD index 4dea3196c..5d7e6934c 100644 --- a/extra-repos/systemd/phosh/APKBUILD +++ b/extra-repos/systemd/phosh/APKBUILD @@ -7,7 +7,7 @@ maintainer="Newbyte " pkgname=phosh _pkgver=0.55.0 pkgver=9999$_pkgver -pkgrel=1 +pkgrel=2 pkgdesc="Wayland shell for GNOME on mobile devices" # armhf: blocked by gnome-shell-schemas arch="all !armhf" @@ -76,7 +76,10 @@ subpackages=" $pkgname-schemas::noarch $pkgname-systemd " -source="https://sources.phosh.mobi/releases/phosh/phosh-${_pkgver/_/.}.tar.xz" +source="https://sources.phosh.mobi/releases/phosh/phosh-${_pkgver/_/.}.tar.xz + use-after-free-fix.patch + extend-timeout-with-pid.patch + " builddir="$srcdir/$pkgname-${_pkgver/_/.}" somask="libphoshsearch.so" # crossdirect disabled because the ARMv7 cross compiler crashes internally with LTO @@ -126,4 +129,6 @@ schemas() { sha512sums=" 42bddb9a24ae3a4227732200bdce9d11a1643341ea16590dfa18098794325fabc678568f4c9cc67891f126003c3219a5087ea412005e89a1c6843ad3ce3f9d79 phosh-0.55.0.tar.xz +8bb798937339eaed1a85f5d6577b9c0ef48047300ccc8c241ffda23f834c7b8c50f8a87aa7cec42ad74aed6397fab6b2f0504284527d0bf2e85a35188c40f41b use-after-free-fix.patch +74972b2cca415a976b5e3d9b6f8cc7098e4321e0c38e18d2ccc1243912056d53d73ce65626e9bff7f32535b6e41dd9b31dc3c3237f516acd411fe7ac34e47e5c extend-timeout-with-pid.patch " diff --git a/extra-repos/systemd/phosh/extend-timeout-with-pid.patch b/extra-repos/systemd/phosh/extend-timeout-with-pid.patch new file mode 100644 index 000000000..ae647bd17 --- /dev/null +++ b/extra-repos/systemd/phosh/extend-timeout-with-pid.patch @@ -0,0 +1,205 @@ +From a79be9dbc846e469aa36fb0bd57d745e456c20ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Guido=20G=C3=BCnther?= +Date: Mon, 18 May 2026 13:12:58 +0200 +Subject: [PATCH 1/3] app-tracker: Better preserve pid +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fixes: f58db9a60 ("Add app-tracker") +Signed-off-by: Guido Günther +Part-of: +--- + src/app-tracker.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/app-tracker.c b/src/app-tracker.c +index d92a7378d..dd795ba06 100644 +--- a/src/app-tracker.c ++++ b/src/app-tracker.c +@@ -188,9 +188,11 @@ update_app_state (PhoshAppTracker *self, + g_return_val_if_fail (state, NULL); + + /* Changing pid is not allowed */ +- g_return_val_if_fail (!state->pid || (state->pid && state->pid != pid), state); ++ if (state->pid && pid && state->pid != pid) ++ g_warning ("Ignoring pid change %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT, state->pid, pid); ++ else if (pid) ++ state->pid = pid; + +- state->pid = pid; + g_debug ("Pid %" G_GINT64_FORMAT ", startup-id: %s got state %d", + state->pid, + state->startup_id, +-- +GitLab + + +From 4f085ebb9d3a566bf919a124dab67afbfd4d7a68 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Guido=20G=C3=BCnther?= +Date: Tue, 19 May 2026 10:40:40 +0200 +Subject: [PATCH 2/3] toplevel-manager: Move timeout to app-tracker +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is where other parts of the shell get the app tracking +data from + +Signed-off-by: Guido Günther +Part-of: +--- + src/app-tracker.h | 2 ++ + src/toplevel-manager.c | 4 +--- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/app-tracker.h b/src/app-tracker.h +index b880c328f..6dcd6a304 100644 +--- a/src/app-tracker.h ++++ b/src/app-tracker.h +@@ -14,6 +14,8 @@ G_BEGIN_DECLS + + #define PHOSH_TYPE_APP_TRACKER (phosh_app_tracker_get_type ()) + ++#define APP_TRACKER_MAX_INITIAL_TOPLEVEL_TIMEOUT 30 /* s */ ++ + G_DECLARE_FINAL_TYPE (PhoshAppTracker, phosh_app_tracker, PHOSH, APP_TRACKER, GObject) + + PhoshAppTracker *phosh_app_tracker_new (void); +diff --git a/src/toplevel-manager.c b/src/toplevel-manager.c +index 27511088e..806a16fce 100644 +--- a/src/toplevel-manager.c ++++ b/src/toplevel-manager.c +@@ -42,8 +42,6 @@ enum { + }; + static guint signals[N_SIGNALS]; + +-#define MAX_INITIAL_TOPLEVEL_TIMEOUT 30 /* s */ +- + typedef struct { + GAppInfo *app_info; + guint timeout_id; +@@ -93,7 +91,7 @@ launching_app_info_new (PhoshToplevelManager *toplevel_manager, GAppInfo *app_in + info->app_info = g_object_ref (app_info); + info->manager = toplevel_manager; + +- info->timeout_id = g_timeout_add_seconds_once (MAX_INITIAL_TOPLEVEL_TIMEOUT, ++ info->timeout_id = g_timeout_add_seconds_once (APP_TRACKER_MAX_INITIAL_TOPLEVEL_TIMEOUT, + on_initial_toplevel_timeout, + info); + return info; +-- +GitLab + + +From 5ec806ff1a4aa8b1e564e1a825f8b77b98b61cef Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Guido=20G=C3=BCnther?= +Date: Mon, 18 May 2026 13:20:57 +0200 +Subject: [PATCH 3/3] app-tracker: Give apps we have a PID for more time to + start +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As long as we have a PID we give it more time up to a maximum, if the +PID goes away we still wait a bit in case it forked. + +This is a simple improvement to help e.g. slow Firefox startup. + +Signed-off-by: Guido Günther +Part-of: +--- + src/app-tracker.c | 38 ++++++++++++++++++++++++++++++++------ + 1 file changed, 32 insertions(+), 6 deletions(-) + +diff --git a/src/app-tracker.c b/src/app-tracker.c +index dd795ba06..88ee165c2 100644 +--- a/src/app-tracker.c ++++ b/src/app-tracker.c +@@ -25,7 +25,11 @@ + #include + #include + ++/* Startup timeout when we don't track the spawning process */ + #define STARTUP_TIMEOUT 5 ++/* Startup timeout when we track the spawning process */ ++#define STARTUP_TRACKED_TIMEOUT (APP_TRACKER_MAX_INITIAL_TOPLEVEL_TIMEOUT * 0.9) ++/* Startup timeout for debugging activation issues */ + #define DEBUG_STARTUP_TIMEOUT 30 + + /** +@@ -82,9 +86,13 @@ typedef struct { + PhoshAppStateFlags state; + + char *startup_id; /* (owned) */ +- guint timeout_id; + GDesktopAppInfo *info; /* (owned) */ + PhoshAppTracker *tracker; /* (unowned) */ ++ struct { ++ guint id; ++ guint waited; ++ guint interval; ++ } timeout; + } PhoshAppState; + + struct _PhoshAppTracker { +@@ -111,16 +119,33 @@ on_startup_timeout (gpointer data) + g_warning ("Hit timeout for '%s' with startup id: '%s' although it's up", + g_app_info_get_name (G_APP_INFO (state->info)), + state->startup_id); +- state->timeout_id = 0; ++ state->timeout.id = 0; + return G_SOURCE_REMOVE; + } + + if (!g_hash_table_contains (state->tracker->apps, state->startup_id)) { + g_warning ("No info for startup_id '%s' found", state->startup_id); +- state->timeout_id = 0; ++ state->timeout.id = 0; + return G_SOURCE_REMOVE; + } + ++ state->timeout.waited += state->timeout.interval; ++ /* If we have a PID we can be more thorough */ ++ if (state->pid && state->timeout.waited < STARTUP_TRACKED_TIMEOUT) { ++ /* TODO: track pidfd on Linux*/ ++ if (!kill (state->pid, 0)) { ++ g_debug ("Startup id: '%s' has PID, waited %us, giving it more time to start", ++ state->startup_id, ++ state->timeout.waited); ++ ++ return G_SOURCE_CONTINUE; ++ } else { ++ /* PID is gone. As this might be a fork give it one more ++ * iteration to bring up a toplevel */ ++ state->timeout.waited = STARTUP_TRACKED_TIMEOUT; ++ } ++ } ++ + /* We got a "launched" signal but the compositor never reported the app as up */ + g_warning ("Startup of app '%s' with startup id: '%s' timed out", + g_app_info_get_name (G_APP_INFO (state->info)), +@@ -151,8 +176,9 @@ phosh_app_state_new (GDesktopAppInfo *info, + state->state = flags; + state->info = g_object_ref (info); + state->tracker = tracker; +- state->timeout_id = g_timeout_add_seconds (timeout, on_startup_timeout, state); +- g_source_set_name_by_id (state->timeout_id, "[phosh] state timeout"); ++ state->timeout.id = g_timeout_add_seconds (timeout, on_startup_timeout, state); ++ state->timeout.interval = timeout; ++ g_source_set_name_by_id (state->timeout.id, "[phosh] state timeout"); + + g_debug ("Pid %" G_GINT64_FORMAT ", '%s', startup-id: %s got state %d", + state->pid, +@@ -167,7 +193,7 @@ phosh_app_state_new (GDesktopAppInfo *info, + static void + phosh_app_state_free (PhoshAppState *state) + { +- g_clear_handle_id (&state->timeout_id, g_source_remove); ++ g_clear_handle_id (&state->timeout.id, g_source_remove); + g_object_unref (state->info); + g_free (state->startup_id); + +-- +GitLab + diff --git a/extra-repos/systemd/phosh/use-after-free-fix.patch b/extra-repos/systemd/phosh/use-after-free-fix.patch new file mode 100644 index 000000000..2b791f791 --- /dev/null +++ b/extra-repos/systemd/phosh/use-after-free-fix.patch @@ -0,0 +1,54 @@ +From 19f233f003a3161e913a81a5965dfeda6858c430 Mon Sep 17 00:00:00 2001 +From: Domenico Iezzi +Date: Sat, 30 May 2026 09:57:09 +0200 +Subject: [PATCH] app-tracker: Fix use-after-free in on_startup_timeout + +When app startup times out and the on_startup_timeout callback is +invoked, it emits the APP_FAILED signal and removes the current +PhoshAppState from the hash table in line 128. In line 131 we try to +access this state variable to set timeout_id to 0, but the value was +freed a few lines above by g_hash_table_remove, resulting in a +use-after-free. + +This fix move the `state->timeout_id = 0` call before early returns, +when we are sure the state object is still valid. + +Signed-off-by: Domenico Iezzi +Part-of: +--- + src/app-tracker.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/app-tracker.c b/src/app-tracker.c +index 1bb83839b..d92a7378d 100644 +--- a/src/app-tracker.c ++++ b/src/app-tracker.c +@@ -111,12 +111,14 @@ on_startup_timeout (gpointer data) + g_warning ("Hit timeout for '%s' with startup id: '%s' although it's up", + g_app_info_get_name (G_APP_INFO (state->info)), + state->startup_id); +- goto out; ++ state->timeout_id = 0; ++ return G_SOURCE_REMOVE; + } + + if (!g_hash_table_contains (state->tracker->apps, state->startup_id)) { + g_warning ("No info for startup_id '%s' found", state->startup_id); +- goto out; ++ state->timeout_id = 0; ++ return G_SOURCE_REMOVE; + } + + /* We got a "launched" signal but the compositor never reported the app as up */ +@@ -127,8 +129,6 @@ on_startup_timeout (gpointer data) + g_signal_emit (state->tracker, signals[APP_FAILED], 0, state->info, state->startup_id); + g_hash_table_remove (state->tracker->apps, state->startup_id); + +- out: +- state->timeout_id = 0; + return G_SOURCE_REMOVE; + } + +-- +GitLab +