Skip to content

test(daemon): retire the listen socket with its owner - #1833

Merged
ScriptedAlchemy merged 3 commits into
masterfrom
cursor/retire-daemon-listen-endpoint-464e
Sep 19, 2026
Merged

ScriptedAlchemy merged 3 commits into
masterfrom
cursor/retire-daemon-listen-endpoint-464e

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

Summary

  • A reaped test daemon no longer leaves its Unix socket accepting. The next spawn refuses a path that is still live, and does not wait that path out.
  • branch_search_serves_a_committed_generation_behind_dirty_worktree_state (tip 3f71bccb2dba) failed because init drops its daemon and the following spawn immediately treats an inherited listen descriptor as a live daemon.

Motivation

Push CI on bc2ced4882 marked branch_search_serves_a_committed_generation_behind_dirty_worktree_state flaky: refusing to replace a live test daemon. The follow-up waited up to 10s for the path to stop accepting. That treats the leak as a race.

tracedecay daemon run unlinks its socket on SIGTERM, before drain. The harness force-stops with SIGKILL, which skips that cleanup. A child that inherited the listen descriptor across fork keeps accepting on the same path after the leader is reaped. init_project_fixture then spawns the replacement and the instantaneous check reports a live daemon.

Changes

  • terminate_and_reap signals the leader's process group, while that pid is still the live leader, then reaps the leader. Signaling a recycled pid is avoided.
  • A daemon records the socket it bound. After the owner is reaped, that path is unlinked. A descriptor inherited by a subprocess that left the group cannot keep the path connectable.
  • The 10s predecessor wait is gone. A path that still accepts is a daemon this call did not stop.
  • reaped_owner_releases_an_inherited_listen_socket binds a socket, forks a child that holds the descriptor, drops the owner, and asserts the path neither exists nor accepts.

.github/workflows/ci.yml is unchanged. No pull_request trigger was added.

Test plan

  • cargo test -p tracedecay --features test-transport --test transport_acceptance_suite daemon_fault_harness_test::reaped_owner_releases_an_inherited_listen_socket -- --exactok. 1 passed; 0 failed; 0 ignored; 0 measured; 12 filtered out
  • Full workspace nextest is the push CI lane, not this slice

Checklist

  • No secrets, credentials, or .env files included
  • CHANGELOG.md updated (test harness only; no user-facing change)
  • Breaking changes documented (none)
Open in Web Open in Cursor 

SIGKILL skips the daemon's endpoint unlink. A child that inherited the
listen descriptor still accepts on that path, so the next spawn reports a
live daemon. branch_search init does exactly that: spawn, init, drop,
spawn again. Waiting for the path to go quiet papers over the leak.

Kill the owner's process group, then unlink the socket the owner bound.
A path that still accepts is a daemon this call did not stop.

Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
@changeset-bot

changeset-bot Bot commented Sep 19, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 97288d7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ScriptedAlchemy
ScriptedAlchemy marked this pull request as ready for review September 19, 2026 06:45
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

Harness-side of the same listen-socket leak as #1819 / #1831. Prefer merging production (#1819/#1831) then this test harness, or folding into #1819 if the common/mod.rs stop path already covers it.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 19, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-19T06:49:02.462874Z 3034d5a Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3034d5ad79

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/tracedecay/tests/common/mod.rs Outdated
Comment on lines +808 to +809
if terminate_and_reap(&mut self.child).is_ok() {
self.retire_owned_unix_endpoint();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Retire the socket when wait_for_exit reaps the owner

When wait_for_exit reaps a daemon, owned_unix_endpoint remains set. Existing graceful-restart paths such as indexing_lifecycle_test.rs:375-384 then assign daemon = spawn_tracedecay_daemon_with(...); the replacement is spawned and binds the same path before the overwritten guard is dropped, so this Drop unlinks the replacement daemon's live socket and subsequent requests cannot connect. Retire the endpoint when try_wait/wait_for_exit observes an exit, or otherwise ensure it is cleared before a replacement is spawned.

Useful? React with 👍 / 👎.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

Cancelled CI run 35427490131: this fixes the same defect as f2ab808 + 8b75523 (clone-postings occurrence indexes, per-page resume reads) on fix/master-ci-green-3 (PR #1797). After #1797 lands I will merge master into this branch; anything that survives gets its own review and run, otherwise the PR closes as superseded.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

Correction to my previous comment: this PR is not a duplicate of the clone-postings fix; that text was meant for #1824/#1830. I cancelled the run only to keep the shared runner queue (2 concurrent, ~20 deep) moving while #1797 waits; this PR gets its own review agent and a fresh dispatch afterwards. Apologies for the noise.

ScriptedAlchemy and others added 2 commits September 19, 2026 07:22
The restart journeys reassign the guard: `daemon = spawn_...` evaluates
the RHS first, so the successor binds `.tracedecay/daemon.sock` before
the predecessor guard is dropped. A predecessor that already exited on
SIGTERM had unlinked its own socket, so the unconditional retire in
`Drop` removed the *successor's* live path. Every later connect in
`ignored_dependency_admission_survives_physical_daemon_restart_without_widening`
and `mounted_incremental_lifecycle_preserves_only_complete_compatible_generations`
then failed with ENOENT.

Retire the recorded endpoint only when this call force-stopped a live
child. A child that exited on its own already ran its own cleanup, so
there is nothing this guard still owns.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

Folded into integration batch #1848 (branch ci/pr-batch-c, CI run 35431957131) after the lane review verdict MERGE with fixes pushed here. This PR is merged once that run is green.

ScriptedAlchemy added a commit that referenced this pull request Sep 19, 2026
tests/common/mod.rs takes #1819's harness wholesale (publisher registry
for socket release, reap tracking) over #1833's; #1833's regression test
now records its socket through release_socket_on_stop. In
publication_store.rs, #1819's commit_observed_pointer keeps #1805's
require_regular_pointer_slot check ahead of the read and maps the rename
error through map_pointer_io so directory faults stay in the publication
family.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ScriptedAlchemy
ScriptedAlchemy merged commit 19c8950 into master Sep 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants