fix: serialize builds so overlapping rebuilds cannot leave an orphaned bin running by erinok · Pull Request #948 · air-verse/air · GitHub
Skip to content

fix: serialize builds so overlapping rebuilds cannot leave an orphaned bin running - #948

Open
erinok wants to merge 1 commit into
air-verse:masterfrom
erinok:fix-overlapping-builds
Open

erinok wants to merge 1 commit into
air-verse:masterfrom
erinok:fix-overlapping-builds

Conversation

@erinok

@erinok erinok commented Oct 16, 2026

Copy link
Copy Markdown

Fixes #947.

A superseded build that finished removed the newest build's token from buildRunCh, so the next change could not cancel that build and two builds ran at once. When both finished together, both stopped and restarted the bin, and the engine kept a handle on only one of the processes: the other kept running (holding the app's port) even after air exited.

Builds now take a mutex, and start() closes the newest build's own stop channel, so a stop signal still never reaches a newer build (#784). This replaces buildRunCh and the two tests that exercised its internals; the new test also checks that the surviving process is the newest.

TestOverlappingBuildsLeaveOneRunningBin scripts the failing interleaving with real processes: build 1 is superseded by build 2 and finishes first, then build 3 starts, and builds 2 and 3 are released together through a FIFO. It fails 10 of 10 runs on master and passes 10 of 10 with this change.

Possible follow-up: runBin registers the new process with binStopCh from a goroutine, so a very fast build right after a restart could still miss it; we don't have a reliable repro, so no fix is attempted here.

Validation: golangci-lint v2.6.1 reports 0 issues. go test -race ./runner matches master locally on macOS (TestGetLoggerFallsBackToRawLogger and TestShouldIncludeIncludedFileWithoutIncludedExt fail on master too).

Author: Claude Opus 5.5

…d bin running

A superseded build that finished removed the newest build's token from buildRunCh, so the
next change could not cancel that build and two builds ran at once. When both finished
together, both stopped and restarted the bin, and the engine kept a handle on only one of
the processes: the other kept running (holding the app's port) even after air exited.

Builds now take a mutex, and start() closes the newest build's own stop channel, so a stop
signal still never reaches a newer build (air-verse#784).
@erinok
erinok force-pushed the fix-overlapping-builds branch from 7464a67 to b2682d2 Compare October 16, 2026 23:25
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.

Overlapping rebuilds can leave an orphaned app process running (port stays in use)

1 participant