Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A 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.

Inbox
ReportR-1503GitHub issuePublicFixed

`omarchy update` lock leaks through AUR daemons (adb), so later updates report one is already running

Reported by kdriedger · filed Aug 24, 2026 · open at source

In the audited area (lock) — decided by agents · verified. Not validated yet.

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?
AreaIn the audited arealock· Decided by agents · verified
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. So far: in the audited area (lock) — decided by agents · verified; matches no known issue — decided by agents · verified. The outcome (valid, duplicate, not a bug, …) is not decided yet. See the decision.

Original report

`omarchy update` lock leaks through AUR daemons (adb), so later updates report one is already runningrevision 1 · captured 2026-09-28 21:24 UTC via poll

System details

  • Omarchy: 4.0.0-1 (stable)
  • Kernel: 7.1.8-arch1-3
  • CPU: Intel Core i5-7300HQ
  • GPU: Intel HD Graphics 630 + NVIDIA GeForce GTX 1050 Mobile

What's wrong?

After an omarchy update that touches AUR packages, later omarchy update runs abort immediately with:

An Omarchy update is already running.

even though nothing is updating. The flock is still held by a daemon spawned during the previous update.

On this machine the leftover holder was adb, started from a flutter-beta AUR build:

$ fuser -v $XDG_RUNTIME_DIR/omarchy-update.lock
                     USER        PID ACCESS COMMAND
/run/user/1000/omarchy-update.lock:
                     linuxbox  139567 F.... adb

$ ls -l /proc/139567/fd/10
/proc/139567/fd/10 -> /run/user/1000/omarchy-update.lock

$ tr '\0' ' ' < /proc/139567/cmdline; echo
adb -L tcp:5037 fork-server server --reply-fd 4

$ readlink /proc/139567/cwd
/home/linuxbox/.cache/yay/flutter-beta/src/flutter

$ ps -o pid,ppid,lstart,cmd -p 139567
# PPID is user systemd; the update that spawned it is long gone

omarchy-update-lock opens the lock without O_CLOEXEC and execs the update:

exec {OMARCHY_UPDATE_LOCK_FD}>"$lock_path"
flock -n "$OMARCHY_UPDATE_LOCK_FD"
export OMARCHY_UPDATE_LOCK_FD
exec "$@"

Every child inherits that fd. omarchy-update-aur-pkgs runs yay -Sua, and packages such as Flutter start adb which daemonizes onto user systemd and keeps the fd open after the update exits. The next omarchy-update-lock run then fails the non-blocking flock.

This is the same leak omarchy-update-stay-awake already special-cases for systemd-inhibit ({OMARCHY_UPDATE_LOCK_FD}>&-), and docs/update-process.md already documents why:

That inhibitor outlives the step that starts it, so an update killed before cleanup would otherwise leave it holding the flock indefinitely — blocking later updates

AUR/yay children are the same class of process and do not get that close.

Steps to reproduce

  1. Have an AUR package installed whose build or post-install starts a long-lived daemon that does not close extra fds (Flutter/adb is a reliable one).
  2. Run omarchy update far enough for omarchy-update-aur-pkgs / yay -Sua to run.
  3. Let the update finish (or abort after that step). Confirm no omarchy-update process remains.
  4. Run omarchy update again.

Expected behavior

The lock is released when the omarchy update process tree exits. A later update can start.

Actual behavior

An Omarchy update is already running. The lock file is held by the leftover daemon (adb here). Removing the lock path (rm -f "$XDG_RUNTIME_DIR/omarchy-update.lock") unblocks the next run because the next open creates a new inode; killing the daemon also works.

Suggested fix

Do not let children inherit the lock fd. Two options that keep the current "parent holds the flock" model:

  1. After omarchy-update-lock held succeeds, set FD_CLOEXEC on OMARCHY_UPDATE_LOCK_FD so later yay/adb/systemd-inhibit children cannot keep it. held still works in the update process itself because it inspects /proc/$$/fd.
  2. Stop execing the update into the lock-holder. Have omarchy-update-lock run keep the flock in the parent and spawn the update with the fd closed ({OMARCHY_UPDATE_LOCK_FD}>&-), using an env flag instead of held to avoid re-acquire. That is what flock --close is for.

Option 2 matches the stay-awake comment in docs/update-process.md and does not depend on every child remembering to close the fd.

Workaround

rm -f "${XDG_RUNTIME_DIR}/omarchy-update.lock"
View raw text
### System details

- Omarchy: 4.0.0-1 (stable)
- Kernel: 7.1.8-arch1-3
- CPU: Intel Core i5-7300HQ
- GPU: Intel HD Graphics 630 + NVIDIA GeForce GTX 1050 Mobile

### What's wrong?

After an `omarchy update` that touches AUR packages, later `omarchy update` runs abort immediately with:

```
An Omarchy update is already running.
```

even though nothing is updating. The flock is still held by a daemon spawned during the previous update.

On this machine the leftover holder was `adb`, started from a `flutter-beta` AUR build:

```
$ fuser -v $XDG_RUNTIME_DIR/omarchy-update.lock
                     USER        PID ACCESS COMMAND
/run/user/1000/omarchy-update.lock:
                     linuxbox  139567 F.... adb

$ ls -l /proc/139567/fd/10
/proc/139567/fd/10 -> /run/user/1000/omarchy-update.lock

$ tr '\0' ' ' < /proc/139567/cmdline; echo
adb -L tcp:5037 fork-server server --reply-fd 4

$ readlink /proc/139567/cwd
/home/linuxbox/.cache/yay/flutter-beta/src/flutter

$ ps -o pid,ppid,lstart,cmd -p 139567
# PPID is user systemd; the update that spawned it is long gone
```

`omarchy-update-lock` opens the lock without `O_CLOEXEC` and `exec`s the update:

```bash
exec {OMARCHY_UPDATE_LOCK_FD}>"$lock_path"
flock -n "$OMARCHY_UPDATE_LOCK_FD"
export OMARCHY_UPDATE_LOCK_FD
exec "$@"
```

Every child inherits that fd. `omarchy-update-aur-pkgs` runs `yay -Sua`, and packages such as Flutter start `adb` which daemonizes onto user systemd and keeps the fd open after the update exits. The next `omarchy-update-lock run` then fails the non-blocking flock.

This is the same leak `omarchy-update-stay-awake` already special-cases for `systemd-inhibit` (`{OMARCHY_UPDATE_LOCK_FD}>&-`), and `docs/update-process.md` already documents why:

> That inhibitor outlives the step that starts it, so an update killed before cleanup would otherwise leave it holding the flock indefinitely — blocking later updates

AUR/yay children are the same class of process and do not get that close.

#### Steps to reproduce

1. Have an AUR package installed whose build or post-install starts a long-lived daemon that does not close extra fds (Flutter/`adb` is a reliable one).
2. Run `omarchy update` far enough for `omarchy-update-aur-pkgs` / `yay -Sua` to run.
3. Let the update finish (or abort after that step). Confirm no `omarchy-update` process remains.
4. Run `omarchy update` again.

#### Expected behavior

The lock is released when the `omarchy update` process tree exits. A later update can start.

#### Actual behavior

`An Omarchy update is already running.` The lock file is held by the leftover daemon (`adb` here). Removing the lock path (`rm -f "$XDG_RUNTIME_DIR/omarchy-update.lock"`) unblocks the next run because the next open creates a new inode; killing the daemon also works.

#### Suggested fix

Do not let children inherit the lock fd. Two options that keep the current "parent holds the flock" model:

1. After `omarchy-update-lock held` succeeds, set `FD_CLOEXEC` on `OMARCHY_UPDATE_LOCK_FD` so later `yay`/`adb`/`systemd-inhibit` children cannot keep it. `held` still works in the update process itself because it inspects `/proc/$$/fd`.
2. Stop `exec`ing the update into the lock-holder. Have `omarchy-update-lock run` keep the flock in the parent and spawn the update with the fd closed (`{OMARCHY_UPDATE_LOCK_FD}>&-`), using an env flag instead of `held` to avoid re-acquire. That is what `flock --close` is for.

Option 2 matches the stay-awake comment in `docs/update-process.md` and does not depend on every child remembering to close the fd.

#### Workaround

```bash
rm -f "${XDG_RUNTIME_DIR}/omarchy-update.lock"
```

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

  • Fixed bypr/8081· confirmed

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.

  • Decided by agents · verified: in the audited area (lock)
  • Decided by agents · verified: matches no known issue

The outcome (valid, duplicate, not a bug, …) is not decided yet.