Skip to content

fctl-agent's lock test can fail when another test starts a process #415

Closed

Description

@fctl-sh

What is wrong

protected::tests::finds_who_holds_a_lock in fctl-agent (added in #409) can fail now and then for the reason #413 found in fctl-host's image store lock test, so cargo test -p fctl-agent (and CI's Rust tests) can fail without any change to it. Nobody has seen it fail yet, but the window is there: in a throwaway stress test, where each round took link::lock on a new path, dropped it and asked held again while two threads ran std::process::Command::new("true").status() in a loop, 168 and 179 of 10,000 rounds found the lock still held right after drop(lock), where the test asserts !held(&path).

How it works now

link::lock (crates/fctl-agent/src/link.rs) takes an flock with File::try_lock and returns the File, which lets go of the lock only by closing. An flock belongs to the open file description, and a process another test forks at that moment (fctl-agent's tests start git, sh and scripts) shares it until it execs, close-on-exec descriptors included. When the fork lands between link::lock and drop(lock), the lock outlives the drop until that process execs, and held finds it held. link::tests::a_second_supervisor_leaves_the_socket_alone retries its claim for this reason (#84); this test doesn't.

What should happen

Compatibility

Tests, and how the supervisor lets go of its lock: no protocol or config change, nothing to release.

Session: https://app.fctl.sh/s/ses_01M6RQNKSZVECTTV7F8RA0FCYF

Activity

  1. added
    bugSomething isn't working
    devcargo xtask, fake-claude, CI, flaky tests
    on Nov 6, 2026
  2. fctl-sh commented on Nov 6, 2026

    @fctl-sh
    ContributorAuthor

    Fixed by #417, merged as 74eb70d: link::lock returns a guard that unlocks before its file closes, and protected::held unlocks the lock it takes to check, so a process another test forks no longer keeps either held. finds_who_holds_a_lock keeps copies of both files open across the drop and fails every time without the unlocks; CI passed. It is on main, waiting for the next release (no tag contains it yet); since it changes only how fctl-agent lets go of its lock, nothing needs deploying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdevcargo xtask, fake-claude, CI, flaky tests

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions