From 8f6be539109e45e2e89fd4bc949ad4b7477b5df9 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 24 Jul 2026 07:45:29 -0700 Subject: [PATCH] quickshell-git: patch crash-relaunch env leak After a crash relaunch, quickshell kept __QUICKSHELL_CRASH_* and the instance-info fd in its environment, so every child it spawned inherited them and any `qs` invocation from those children booted a duplicate shell instead of running its command (phantom instances on every menu-launched picker after a crash). Patch carried on the fix-crash-env-leak branch of https://github.com/omacom-io/quickshell Co-Authored-By: Claude Fable 5 --- ...0001-launch-clear-crash-relaunch-env.patch | 81 +++++++++++++++++++ pkgbuilds/quickshell-git/PKGBUILD | 17 +++- 2 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 pkgbuilds/quickshell-git/0001-launch-clear-crash-relaunch-env.patch diff --git a/pkgbuilds/quickshell-git/0001-launch-clear-crash-relaunch-env.patch b/pkgbuilds/quickshell-git/0001-launch-clear-crash-relaunch-env.patch new file mode 100644 index 0000000..401faa9 --- /dev/null +++ b/pkgbuilds/quickshell-git/0001-launch-clear-crash-relaunch-env.patch @@ -0,0 +1,81 @@ +From c4b9162e4f288d8d17c6d0a2cb5f05d9c4a5c4e5 Mon Sep 17 00:00:00 2001 +From: David Heinemeier Hansson +Date: Fri, 24 Jul 2026 07:36:46 -0700 +Subject: [PATCH] launch: clear crash relaunch env after consuming it + +The crash handler re-execs the crashed process with __QUICKSHELL_CRASH_INFO_FD, +__QUICKSHELL_CRASH_DUMP_PID and __QUICKSHELL_CRASH_SIGNAL in its environment, +with CLOEXEC stripped from the info fd so it survives the exec. + +The relaunched shell kept all of that for its lifetime: the variables stayed +in its environment and the info fd stayed open until shutdown. Every process +it spawned inherited them, so any quickshell invocation from such a process +(e.g. `qs ipc` from a script launched by the shell) mistook itself for a +crash relaunch and booted the crashed instance's config instead of running +its own command, registering a duplicate instance of the shell. + +Consume the relaunch info, then close the fd and unset the variables before +launching. + +Co-Authored-By: Claude Fable 5 +--- + src/launch/main.cpp | 33 +++++++++++++++++++++++---------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +diff --git a/src/launch/main.cpp b/src/launch/main.cpp +index efd6628..07d5e71 100644 +--- a/src/launch/main.cpp ++++ b/src/launch/main.cpp +@@ -30,17 +30,31 @@ void checkCrashRelaunch(char** argv, QCoreApplication* coreApplication) { + + if (!lastInfoFdStr.isEmpty()) { + auto lastInfoFd = lastInfoFdStr.toInt(); ++ auto crashPid = qEnvironmentVariable("__QUICKSHELL_CRASH_DUMP_PID").toInt(); + +- QFile file; +- if (!file.open(lastInfoFd, QFile::ReadOnly, QFile::AutoCloseHandle)) { +- qFatal() << "Failed to open crash info fd. Cannot restart."; ++ RelaunchInfo info; ++ ++ { ++ QFile file; ++ if (!file.open(lastInfoFd, QFile::ReadOnly, QFile::AutoCloseHandle)) { ++ qFatal() << "Failed to open crash info fd. Cannot restart."; ++ } ++ ++ file.seek(0); ++ ++ auto ds = QDataStream(&file); ++ ds >> info; + } + +- file.seek(0); +- +- auto ds = QDataStream(&file); +- RelaunchInfo info; +- ds >> info; ++ // The crash handler stripped CLOEXEC from the info fd and injected the crash ++ // variables into the environment so they survive the re-exec. Both are consumed ++ // at this point and must not leak further: children of the relaunched shell ++ // inherit its environment, so another quickshell invocation from one of them ++ // (e.g. `qs ipc` from a spawned script) would relaunch the crashed config ++ // instead of running its own command. ++ qunsetenv("__QUICKSHELL_CRASH_INFO_FD"); ++ qunsetenv("__QUICKSHELL_CRASH_DUMP_PID"); ++ qunsetenv("__QUICKSHELL_CRASH_SIGNAL"); + + LogManager::init( + !info.noColor, +@@ -50,8 +64,7 @@ void checkCrashRelaunch(char** argv, QCoreApplication* coreApplication) { + info.logRules + ); + +- qCritical().nospace() << "Quickshell has crashed under pid " +- << qEnvironmentVariable("__QUICKSHELL_CRASH_DUMP_PID").toInt() ++ qCritical().nospace() << "Quickshell has crashed under pid " << crashPid + << " (Coredumps will be available under that pid.)"; + + qCritical() << "Further crash information is stored under" +-- +2.55.0 + diff --git a/pkgbuilds/quickshell-git/PKGBUILD b/pkgbuilds/quickshell-git/PKGBUILD index 0b2faf9..8f98c0d 100644 --- a/pkgbuilds/quickshell-git/PKGBUILD +++ b/pkgbuilds/quickshell-git/PKGBUILD @@ -3,7 +3,7 @@ _pkgname=quickshell pkgname="$_pkgname-git" pkgver=0.3.0.r17.ge649d24 -pkgrel=1 +pkgrel=2 pkgdesc='Flexible toolkit for making desktop shells with QtQuick' arch=(x86_64 aarch64) url='https://git.outfoxxed.me/quickshell/quickshell' @@ -38,11 +38,22 @@ conflicts=("$_pkgname") _pkgsrc="$_pkgname" source=("$_pkgsrc"::"git+$url.git#commit=e649d247498512464457aefcd05b73038c4e65a1" - quickshell-check.hook) + quickshell-check.hook + 0001-launch-clear-crash-relaunch-env.patch) sha256sums=('SKIP' - '8543e21aeaaa5441b73a679160e7601a957f16c433e8d6bd9257e80bd0e94083') + '8543e21aeaaa5441b73a679160e7601a957f16c433e8d6bd9257e80bd0e94083' + '867f154dd3ea09ec751664e84fe9da47f6e0321b77abaa0cf3eb391a978de305') +prepare() { + cd "$_pkgsrc" + # After a crash relaunch, quickshell leaks __QUICKSHELL_CRASH_* into the + # environment of every child it spawns, so any `qs` call from those children + # boots a duplicate shell instead of running its command. + # Carried on the fix-crash-env-leak branch of https://github.com/omacom-io/quickshell + patch -Np1 -i "$srcdir/0001-launch-clear-crash-relaunch-env.patch" +} + pkgver() { cd "$_pkgsrc" git describe --long --tags --abbrev=7 --exclude='*[a-zA-Z][a-zA-Z]*' \