Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.
Dismissing the Speed Test panel orphans 8 upload workers that keep saturating the uplink
Reported by orospakr · filed Aug 30, 2026Closed upstream on 2026-08-30 by its own reporter orospakr, as a duplicate of #6989 (R-1833). GitHub close reason: not_planned.
At a glance
- 1 · What is claimed?
- Only the report text below — no validator has restated it as checkable claims yet.
- 2 · What does it affect?
- Not yet mapped to any requirement or component.
- 3 · Is it reproducible?
- No validation has been run yet.
- 4 · What remains unclear?
- Not validated yet: no claims, no reproducer.
- 5 · What happens next?
- Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.
Original report
System details
Intel Xeon W-2140B, AMD Radeon Pro Vega 56 (amdgpu), Omarchy 4.0.1-1, Hyprland 0.56.2, quickshell 0.3.1-1, bash 5.3.15, kernel 7.1.8-arch1, Apple iMacPro1,1 (T2)
What's wrong?
Dismissing the Network Speed Test panel leaves up to 8 orphaned omarchy-network-speedtest worker subshells running. They are reparented to systemd --user and keep looping 64 MB POSTs to Netflix OCA nodes indefinitely — the panel is gone, but the uplink stays saturated until the user notices and kills them by hand. Every dismissal leaks another generation.
I hit this by accident (found 8 stray curl uploads pinning my connection long after closing the panel), then reproduced it deterministically.
Steps to reproduce
omarchy-shell shell summon omarchy.speedtest '{}'
sleep 7 # past the 5s download phase, into the upload phase
omarchy-shell shell hide omarchy.speedtest # or just click the overlay's close button
sleep 4
ps -e -o pid=,ppid=,cmd= | grep -F '/omarchy-network-speedtest' | grep -v grepExpected: no output.
Actual — 6 of the 8 workers survive, reparented to PID 1215 (systemd --user):
307860 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
307861 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
307864 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
307865 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
307868 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
307872 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest upEach still has a live curl:
curl -fsS -o /dev/null -X POST --data-binary @- https://ipv4-c001-yul001-beanfield-isp.1.oca.nflxvideo.net/speedtest?c=ca&n=21949...Recovery is pkill -f omarchy-network-speedtest.
Cause
A teardown race between the panel and the script:
omarchy-network-speedtestforks 8 background workers and relies ontrap cleanup EXIT(bin/omarchy-network-speedtest:55-67) to reap them.plugins/panels/speedtest/Panel.qml:50-62close()does the right thing —speedTestProc.running = falsesends SIGTERM.- But
shell.qml:480-494hide()callsclose()and then removes the id fromopenPanelIdsin the same event-loop turn. That flips the Loader'sactivebinding (shell.qml:625) to false, destroying the panel Item — and itsProcess— while bash is still shutting down. - The script can't respond to the SIGTERM instantly: it is blocked in
sleep 1in its sampling loop (:108-128), so it needs up to ~1s to reach the trap. It never gets that long, socleanupnever completes and the 8 workers are orphaned.
Verified both directions: SIGTERM to the script alone cleans up perfectly (0 orphans); SIGKILL reproduces the exact orphan signature above. The speedtest manifest doesn't set keepLoaded, so it's on the destroy-on-hide path.
Possible fixes
Either one alone appears sufficient:
"keepLoaded": trueinplugins/panels/speedtest/manifest.json, so the Item survives the hide andclose()'s SIGTERM lands. One line, but only covers this panel.- Harden the script —
trap cleanup EXIT INT TERM HUP, and put the workers in their own process group so a hard kill takes the children with it. Fixes it for any caller, and makes the script safe to kill from anywhere.
A more general fix would be for hide() to let a plugin finish closing before the Loader is deactivated, since any plugin that spawns a Process is exposed to the same race.
I haven't checked whether omarchy.disk-speedtest has the same problem; its Panel.qml comments suggest the helper cleans up after itself differently, so it may not.
Happy to send a PR for whichever approach you'd prefer.
View raw text
### System details
Intel Xeon W-2140B, AMD Radeon Pro Vega 56 (amdgpu), Omarchy 4.0.1-1, Hyprland 0.56.2, quickshell 0.3.1-1, bash 5.3.15, kernel 7.1.8-arch1, Apple iMacPro1,1 (T2)
### What's wrong?
Dismissing the Network Speed Test panel leaves up to 8 orphaned `omarchy-network-speedtest` worker subshells running. They are reparented to `systemd --user` and keep looping 64 MB `POST`s to Netflix OCA nodes **indefinitely** — the panel is gone, but the uplink stays saturated until the user notices and kills them by hand. Every dismissal leaks another generation.
I hit this by accident (found 8 stray `curl` uploads pinning my connection long after closing the panel), then reproduced it deterministically.
#### Steps to reproduce
```bash
omarchy-shell shell summon omarchy.speedtest '{}'
sleep 7 # past the 5s download phase, into the upload phase
omarchy-shell shell hide omarchy.speedtest # or just click the overlay's close button
sleep 4
ps -e -o pid=,ppid=,cmd= | grep -F '/omarchy-network-speedtest' | grep -v grep
```
Expected: no output.
Actual — 6 of the 8 workers survive, reparented to PID 1215 (`systemd --user`):
```
307860 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
307861 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
307864 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
307865 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
307868 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
307872 1215 /bin/bash /usr/share/omarchy/bin/omarchy-network-speedtest up
```
Each still has a live `curl`:
```
curl -fsS -o /dev/null -X POST --data-binary @- https://ipv4-c001-yul001-beanfield-isp.1.oca.nflxvideo.net/speedtest?c=ca&n=21949...
```
Recovery is `pkill -f omarchy-network-speedtest`.
#### Cause
A teardown race between the panel and the script:
- `omarchy-network-speedtest` forks 8 background workers and relies on `trap cleanup EXIT` (`bin/omarchy-network-speedtest:55-67`) to reap them.
- `plugins/panels/speedtest/Panel.qml:50-62` `close()` does the right thing — `speedTestProc.running = false` sends SIGTERM.
- But `shell.qml:480-494` `hide()` calls `close()` and then removes the id from `openPanelIds` in the **same event-loop turn**. That flips the Loader's `active` binding (`shell.qml:625`) to false, destroying the panel Item — and its `Process` — while bash is still shutting down.
- The script can't respond to the SIGTERM instantly: it is blocked in `sleep 1` in its sampling loop (`:108-128`), so it needs up to ~1s to reach the trap. It never gets that long, so `cleanup` never completes and the 8 workers are orphaned.
Verified both directions: SIGTERM to the script alone cleans up perfectly (0 orphans); SIGKILL reproduces the exact orphan signature above. The speedtest manifest doesn't set `keepLoaded`, so it's on the destroy-on-hide path.
#### Possible fixes
Either one alone appears sufficient:
1. `"keepLoaded": true` in `plugins/panels/speedtest/manifest.json`, so the Item survives the hide and `close()`'s SIGTERM lands. One line, but only covers this panel.
2. Harden the script — `trap cleanup EXIT INT TERM HUP`, and put the workers in their own process group so a hard kill takes the children with it. Fixes it for any caller, and makes the script safe to kill from anywhere.
A more general fix would be for `hide()` to let a plugin finish closing before the Loader is deactivated, since any plugin that spawns a `Process` is exposed to the same race.
I haven't checked whether `omarchy.disk-speedtest` has the same problem; its `Panel.qml` comments suggest the helper cleans up after itself differently, so it may not.
Happy to send a PR for whichever approach you'd prefer.
Validation
Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.
Linked
Not linked to any known issue, other report or change yet.
Decision
Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.
No decision has been recorded yet.