Skip to content

fix(daemon): spare a stale pidfile's PID when evicting - #4512

Merged
atuin-bot merged 1 commit into
mainfrom
fix/daemon-evict-live-pid
Oct 22, 2026
Merged

atuin-bot merged 1 commit into
mainfrom
fix/daemon-evict-live-pid

Conversation

@markovejnovic

@markovejnovic markovejnovic commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

atuin daemon start --force evicts the running daemon before starting its own, and it killed the PID in the pidfile even when no daemon held the pidfile. A daemon that crashed leaves its pidfile behind, and its PID may since have gone to another process. Evicting now signals the PID only while a daemon holds the pidfile.

The regression test dies by SIGTERM without the fix.

Stack (bottom β†’ top)

  1. fix(daemon): spare a stale pidfile's PID when evictingΒ #4512 fix(daemon): spare a stale pidfile's PID when evicting
  2. feat(common): find a process's cgroup under cgroup v1 and v2Β #4513 feat(common): parse a process's cgroups under cgroup v1 and v2
  3. refactor(daemon): keep where the daemon listens behind service::addressΒ #4514 refactor(daemon): keep where the daemon listens behind service::address
  4. refactor(daemon): take up the daemon's socket in SocketHolder, not BackendΒ #4515 refactor(daemon): take up the daemon's socket in SocketHolder, not Backend
  5. fix(daemon): handle daemons not spawned by atuinΒ #4516 feat(daemon): leave a daemon that something else runs to it
  6. feat(daemon): run the daemon as a launchd agent on macOSΒ #4517 feat(daemon): run the daemon as a launchd agent on macOS

Each PR includes the ones below it. Review and merge bottom-up.

@markovejnovic

Copy link
Copy Markdown
Member Author

/merge

@atuin-bot

atuin-bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Landed as ffc6be4 without CI. GitHub shows this merged once it reaches main.

@greptile-apps

greptile-apps Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge.

Summary

Subproc::evict() now checks that the pidfile is held before signaling its PID.

  • Forced daemon starts signal a PID only while its pidfile is held.

Reviews (1) Β· Last reviewed commit: "fix(daemon): spare a stale pidfile's PID..." Β· Reviewed by Greptile

@markovejnovic

Copy link
Copy Markdown
Member Author

/merge

@markovejnovic

Copy link
Copy Markdown
Member Author

/merge

@markovejnovic

Copy link
Copy Markdown
Member Author

/merge yolo

`atuin daemon start --force` evicts the running daemon before starting its own, and it killed the PID in the pidfile even when no daemon held the pidfile. A daemon that crashed leaves its pidfile behind, and its PID may since have gone to another process. Evicting now signals the PID only while a daemon holds the pidfile.

The regression test dies by SIGTERM without the fix.

## Stack (bottom β†’ top)

1. #4512 fix(daemon): spare a stale pidfile's PID when evicting
2. #4513 feat(common): parse a process's cgroups under cgroup v1 and v2
3. #4514 refactor(daemon): keep where the daemon listens behind service::address
4. #4515 refactor(daemon): take up the daemon's socket in SocketHolder, not Backend
5. #4516 feat(daemon): leave a daemon that something else runs to it
6. #4517 feat(daemon): run the daemon as a launchd agent on macOS

Each PR includes the ones below it. Review and merge bottom-up.
@atuin-bot
atuin-bot force-pushed the fix/daemon-evict-live-pid branch from 062412d to ffc6be4 Compare October 22, 2026 01:13
@atuin-bot
atuin-bot merged commit ffc6be4 into main Oct 22, 2026
5 checks passed
@atuin-bot
atuin-bot deleted the fix/daemon-evict-live-pid branch October 22, 2026 01:13
atuin-bot pushed a commit that referenced this pull request Oct 22, 2026
`CgroupV2` finds a process's cgroup in cgroup v2's unified hierarchy, the `0::` line of `/proc/<pid>/cgroup`, and `CgroupV1` the one in the v1 hierarchy a controller or name is bound to, such as systemd's `name=systemd`. The hybrid layout lists both. RHEL 8 and its rebuilds (systemd 239, built with `-Ddefault-hierarchy=legacy`) boot cgroup v1 alone, with no `0::` line: the kernel lists v2's hierarchy only once something mounts it. Nothing calls them yet: a later PR in this stack uses them to tell whether a systemd user unit runs the daemon.

`listed_in`'s cases pass in a standalone crate on macOS. The `reads_the_active_process` tests were not run on this version.

## Stack (bottom β†’ top)

1. #4512 fix(daemon): spare a stale pidfile's PID when evicting
2. #4513 feat(common): find a process's cgroup under cgroup v1 and v2
3. #4514 refactor(daemon): keep where the daemon listens behind service::address
4. #4515 refactor(daemon): take up the daemon's socket in SocketHolder, not Backend
5. #4516 feat(daemon): leave a daemon that something else runs to it
6. #4517 feat(daemon): run the daemon as a launchd agent on macOS

Each PR includes the ones below it. Review and merge bottom-up.
atuin-bot pushed a commit that referenced this pull request Oct 22, 2026
…ss (#4514)

Unix sockets and Windows' TCP port were told apart by cfgs across `service/`. Each platform's `address` module now defines the same names, so the code calling it has no cfgs of its own. The commit lists what moved where.

No behaviour change. Windows clients now pass `--daemonize` as well, which does nothing there. Some public items moved:

- `service::pidfile::SocketPathError` is now `service::address::LocateError`, and `Pidfile::socket_path` is now `DaemonAddress::locate`.
- `client::potential_socket_paths` is gone, and so is the `service::RemoveSocketError` re-export; use `service::address::RemoveSocketError`.
- The pidfile's round-trip proptest now runs on Windows too, over UTF-8 paths only. `AutoOsString`'s own tests round-trip the others.

Includes #4513, so review only the last commit.

- macOS: clippy (default and `--tests`), rustdoc, `atuin-daemon` lib tests and `e2e_daemon` pass.
- Linux (Docker): clippy and the `atuin-common` and `atuin-daemon` lib tests pass.
- Windows (`x86_64-pc-windows-gnu`, cross-compiled): clippy is clean for `atuin-daemon` and `cargo check --tests` passes. Clippy on the `atuin` binary fails with the same 10 errors as main. Not run on Windows itself.

## Stack (bottom β†’ top)

1. #4512 fix(daemon): spare a stale pidfile's PID when evicting
2. #4513 feat(common): find a process's cgroup under cgroup v1 and v2
3. #4514 refactor(daemon): keep where the daemon listens behind service::address
4. #4515 refactor(daemon): take up the daemon's socket in SocketHolder, not Backend
5. #4516 feat(daemon): leave a daemon that something else runs to it
6. #4517 feat(daemon): run the daemon as a launchd agent on macOS

Each PR includes the ones below it. Review and merge bottom-up.
atuin-bot pushed a commit that referenced this pull request Oct 22, 2026
…ckend (#4515)

`Backend::listen` ran inside the daemon, but backends belong to the client, which picks one to start and stop the daemon. Off Linux, `ExternalSystemd` built a `Subproc` only to bind its socket. `SocketHolder` now says who holds the socket, the daemon or systemd, and takes it up. Taking systemd's socket moves into `systemd/`, which off Linux has the daemon bind its own.

No behaviour change. `ExternalSystemd` keeps its `cfg(unix)` gate until the next PR in this stack replaces it.

Includes #4513 and #4514, so review only the last commit. Checked the same way as #4514.

## Stack (bottom β†’ top)

1. #4512 fix(daemon): spare a stale pidfile's PID when evicting
2. #4513 feat(common): find a process's cgroup under cgroup v1 and v2
3. #4514 refactor(daemon): keep where the daemon listens behind service::address
4. #4515 refactor(daemon): take up the daemon's socket in SocketHolder, not Backend
5. #4516 feat(daemon): leave a daemon that something else runs to it
6. #4517 feat(daemon): run the daemon as a launchd agent on macOS

Each PR includes the ones below it. Review and merge bottom-up.
atuin-bot pushed a commit that referenced this pull request Oct 22, 2026
### Bug Fixes

- *(ai)* Import IntoStaticStr from strum_macros, not strum ([&#35;4480](#4480))
- *(ai)* Improve detection of git repositories ([&#35;4450](#4450))
- *(client)* Resolve relative config paths beside config.toml, not the cwd ([&#35;4479](#4479))
- *(config)* Don't print errors twice ([&#35;4501](#4501))
- *(daemon)* Fetch the server's capabilities until a fetch succeeds
- *(daemon)* Spare a stale pidfile's PID when evicting ([&#35;4512](#4512))
- *(daemon)* Handle daemons not spawned by atuin ([&#35;4516](#4516))
- *(output)* Keep quoted words together in output search ([&#35;4502](#4502))
- *(packfile)* Load only the records inside a manifest's range
- *(pty-proxy)* Standalone init with `atuin pty-proxy init` ([&#35;4449](#4449))
- *(pty-proxy)* Wait for input on a non-blocking inherited stdin ([&#35;4486](#4486))
- *(pty-proxy)* Don't re-exec shells running commands from a string or file ([&#35;4414](#4414))
- *(search)* Don't panic when copying with no results ([&#35;4426](#4426))
- *(server)* Let `ATUIN_*` environment variables override server.toml ([&#35;4456](#4456))
- *(update)* Accept ATUIN_GITHUB_TOKEN ([&#35;4262](#4262))
- Remove duplicated word in the no-history stats message ([&#35;4451](#4451))
- Error printing in `?` handler ([&#35;4448](#4448))
- Normalize relative gitdir paths in worktree resolution ([&#35;4506](#4506))
- Upgrade regressions found in release QA ([&#35;4519](#4519))


### Documentation

- Fix ctrl_n_shortcuts default value ([&#35;4458](#4458))
- List all history list --format variables ([&#35;4460](#4460))
- Fix the --reverse default for history list ([&#35;4472](#4472))
- Mention December default in wrapped --year help ([&#35;4476](#4476))


### Features

- *(common)* AbsPath and AbsPathBuf, Path and PathBuf checked to be absolute ([&#35;4481](#4481))
- *(common)* Find a process's cgroup under cgroup v1 and v2 ([&#35;4513](#4513))
- *(daemon)* Run the daemon as a launchd agent on macOS ([&#35;4517](#4517))
- *(pty-proxy)* Window title follows child process ([&#35;4447](#4447))
- *(secrets)* Keep HashiCorp tokens out of history ([&#35;4445](#4445))


### Miscellaneous Tasks

- Give mono its own nixfmt step and scope atuin's to atuin/
- Say a /merge's landed commit gets CI on main
- Rebuild the apt .deb cache for Ubuntu 24.04 ([&#35;4504](#4504))
- Remove the benchmarks ([&#35;4511](#4511))


### Performance

- *(common)* Compile the vendor regexes once ([&#35;4485](#4485))
- *(common)* Drop the tree watcher's file-id cache ([&#35;4492](#4492))
- *(common)* Release a line reader's buffer at the end of the file ([&#35;4494](#4494))
- *(common)* Keep no tree watcher entry for a rejected file ([&#35;4493](#4493))
- *(daemon)* Warm up only a resumed session's unanswered calls ([&#35;4490](#4490))
- *(packfile)* Compress packs in one shot ([&#35;4484](#4484))


### Refactor

- *(daemon)* Managed daemon service with multiple backends ([&#35;4488](#4488))
- *(daemon)* Move daemon startup into the service module ([&#35;4503](#4503))
- *(daemon)* Keep where the daemon listens behind service::address ([&#35;4514](#4514))
- *(daemon)* Take up the daemon's socket in SocketHolder, not Backend ([&#35;4515](#4515))
- *(deps)* Bump clap_complete_nushell from 4.6.0 to 4.6.2 ([&#35;4473](#4473))
- *(deps)* Bump clap_complete from 4.6.9 to 4.6.11 ([&#35;4396](#4396))
- *(deps)* Bump ratatui from 0.30.0 to 0.30.2 ([&#35;4474](#4474))
- *(deps)* Bump certifi from 2025.11.12 to 2026.10.19 in /docs in the uv group across 1 directory ([&#35;4500](#4500))
- *(pty-proxy)* Run on tokio with the parser on its own runtime ([&#35;4482](#4482))
- *(pty-proxy)* Forward captures to the daemon on the proxy's runtime ([&#35;4487](#4487))
- *(pty-proxy)* Rename the screen's parser to Emulator ([&#35;4510](#4510))
- *(pty-proxy)* Migrate output parsing to vte ([&#35;4518](#4518))


### Testing

- *(daemon)* Run the output index tests under rstest ([&#35;4496](#4496))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants