Skip to content

fix: close remaining concurrent solc install races - #255

Merged
DaniPopes merged 3 commits into
masterfrom
mattsse/svm-publish-barrier
Sep 27, 2026
Merged

DaniPopes merged 3 commits into
masterfrom
mattsse/svm-publish-barrier

Conversation

@mattsse

@mattsse mattsse commented Sep 27, 2026 •

Copy link
Copy Markdown
Member

Follow-up to #230, which closed the ETXTBSY races behind foundry-rs/foundry#4736 but left two gaps that its description called out.

A child forked by another thread while the installer's temporary file is open for writing keeps a duplicate of the write handle until it execs. Closing the installer's own handle is not enough, because Linux refuses to execute a file that is open for writing anywhere, so install could still return a binary that fails with Text file busy. The svm solc wrapper and foundry-compilers retry such launches, but other consumers do not. The installer now probes the prepared binary by launching it before the rename, retrying with bounded backoff while the kernel reports it busy, and kills the probe as soon as it starts. If a writer outlives the retries, for example a forked child that never execs, the install fails instead of publishing an unusable binary, and the existing retry loop prepares a new file. The probe only runs on Linux and Android, since macOS executes files that are open for writing.

The new publication_with_forking_thread regression installs while another thread keeps forking children that are slow to exec. On master it failed 30 of 30 stress runs, with one run returning a binary that could not be launched for 31 of 100 installs; with this change it passes 30 of 30.

Windows releases up to 0.7.1 are zip artifacts, so the installed solc.exe never matched the artifact checksum and every install re-extracted the archive over a binary and DLLs that other processes could be running, which Windows refuses. An existing installation is now compared with the solc.exe inside the downloaded archive and reused when it matches. The new can_reinstall_windows_zip_release_while_running test covers this in the Windows CI job; it has not been run on Windows locally.

A child forked by another thread while the installer's temp file is
open for writing keeps a duplicate of the write handle until it execs.
Closing the installer's own handle is not enough: Linux refuses to
execute a file that is open for writing anywhere, so `install` could
return a binary that fails with ETXTBSY, and only consumers that retry
the launch recovered.

Before publishing, launch the prepared binary with bounded retries
while it is busy and kill the probe once it starts. A writer that
outlives the retries fails the install, so the existing retry loop
prepares a new file instead of publishing an unusable one.
Windows releases up to 0.7.1 are zip artifacts whose checksum never
matches the installed solc.exe, so every install re-extracted the
archive over a binary and DLLs that could be in use, which Windows
refuses. Compare an existing installation with the binary inside the
downloaded archive instead.
@mattsse
mattsse requested a review from DaniPopes as a code owner September 27, 2026 08:38
Comment thread crates/svm-rs/src/install.rs Outdated
@DaniPopes
DaniPopes merged commit 09fa0b5 into master Sep 27, 2026
10 checks passed
@DaniPopes
DaniPopes deleted the mattsse/svm-publish-barrier branch September 27, 2026 12:16
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