Skip to content

Release the Bootstrap Lock When a bootstrap.ps1 Run Ends, Not When Its Process Does #3137

Closed

Description

@ptr727

Context

Found while running the Windows-native check owed by #3130 in an interactive pwsh session. Two bootstrap.ps1 runs back to back in the same session: the first ran to completion (it exited 1 on an expected Unknown tool refusal), and the second, started right after it, refused to start.

The Lock Outlives the Run in an Interactive Session

Lock-Directory opens the lock file with [IO.File]::Open(..., 'None') into $script:LOCK and never disposes it, on the grounds stated beside $LOCK: "Held rather than disposed, since the lock it carries lasts until this process ends." That holds for pwsh -File bootstrap.ps1 and for powershell -ExecutionPolicy Bypass -File, where the script's process ends with the run. It does not hold for ./host-setup/bootstrap.ps1 typed at an interactive prompt, which runs the script inside the caller's own process. There the open FileStream survives the script, through both a normal finish and die's exit 1, and keeps the lock until the stream is garbage-collected or the session closes.

Reproduction, in one interactive pwsh session on a host where %LOCALAPPDATA%\host-setup is the bootstrap directory:

./host-setup/bootstrap.ps1 -Agents ALL -Ref develop -DryRun   # runs, then refuses ALL as expected
./host-setup/bootstrap.ps1 -Agents all -Ref develop -DryRun
# ERROR: Could not lock ...\host-setup\tree.lock: The process cannot access the file ... because it is being used by another process.

The error then blames "another bootstrap run", which is the same session's finished run.

Possible Direction

Release the lock when the run ends rather than when the process does: dispose $script:LOCK in the finally around the run (after Invoke-Cleanup, so the cleanup still happens under the lock), and on die's path as well, since exit inside a function leaves the stream open the same way. A test drives two runs in one pwsh process and expects the second to take the lock. bootstrap.sh takes its flock in its own process and is not affected.

Workaround meanwhile: run each bootstrap in a new pwsh window, or as pwsh -File ./host-setup/bootstrap.ps1 ....

Activity

  1. added
    bugSomething isn't working
    pre-existingReview finding classed pre-existing per local-strict-review Disposing of Findings
    scriptA defect in hub tooling
    on Oct 16, 2026
  2. added a commit that references this issue on Oct 16, 2026
    19cfddc
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 workingpre-existingReview finding classed pre-existing per local-strict-review Disposing of FindingsscriptA defect in hub tooling

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions