Repository navigation
fix(devbox): make concurrent devbox run safe on shared script files - #3032
Merged
Merged
Conversation
Every `devbox run` rewrote .devbox/gen/scripts in place, and the cleanup in WriteScriptsToFiles deleted .cmd.sh because it was never in the written set. Concurrent runs in the same project could therefore execute a deleted (127), not yet executable (126), or empty (no output) script. Scripts are now written to a temp file and renamed into place, the cleanup keeps .cmd.sh, and it only removes .sh files so it never touches another writer's temp file. Fixes #3025 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The new concurrent script test calls WriteScriptsToFiles from several goroutines, and with DEVBOX_PRINT_EXEC_TIME set the unguarded headerPrinted flag is a data race under -race. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
@claude ptal |
|
Claude finished @mikeland73's task in 19s —— View job Review of #3032LGTM. I read the diff but didn't run the tests myself. I found no blocking issues. What I checked
Minor, non-blocking
Nothing else to flag. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #3025. Running
devbox runconcurrently in one project could fail with exit 127 (.cmd.sh: No such file or directory) or exit 126 (Permission denied), or exit 0 with no output. The code behind this has been there since #550 (2023), so it isn't a regression.There were two causes:
.cmd.sh.WriteScriptsToFilesremoves every script it didn't just write, and.cmdwas never in that set. Eachdevbox rundeleted the.cmd.shanother run was about to execute.os.Createtruncates the file and then chmods and writes it, so another process could execute it while it was empty or not yet executable.Changes:
.hooks.sh, the devbox.json scripts,.cmd.sh) are written to a temp file in the same directory and renamed into place, using the same pattern aslauncher.writeVersion..cmd.shand only considers*.shfiles, so it never removes another writer's temp file.arbitraryCmdFilenamemoves toshellgen.ArbitraryCmdFilenameso the cleanup can refer to it.internal/debug/time.go: the "Exec times" header flag is now async.Once. Without it, the new test trips-racewhenDEVBOX_PRINT_EXEC_TIMEis set.How was it tested?
TestConcurrentRunScriptFiles: 8 goroutines × 20 runs, each rewriting the scripts and then executing.cmd.sh. Onmainit fails with the same exit 127, exit 126 and empty-output cases as the issue. With this change it passes, including with-race.devbox.json): installed 0.19.0 had 57/200 failures; a build of this branch had 0/200.go test ./internal/devbox ./internal/shellgenpasses, as do thescript,script_exit_on_error,args,quote_escaping,shellception,envandpathtestscripts. Lint is clean.Community Contribution License
All community contributions in this pull request are licensed to the project
maintainers under the terms of the
Apache 2 License.
By creating this pull request, I represent that I have the right to license the
contributions to the project maintainers under the Apache 2 License as stated in
the
Community Contribution License.
🤖 Generated with Claude Code