Skip to content

Commit 1fea7c8

Browse files
Merge pull request #6461 from NomicFoundation/add-mutex-compiler-list
Add mutex when downloading compiler list
2 parents 52fbf8c + c9d81f9 commit 1fea7c8

File tree

3 files changed

+27
-18
lines changed

3 files changed

+27
-18
lines changed

.changeset/polite-crabs-relax.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@nomicfoundation/hardhat-utils": patch
3+
"hardhat": patch
4+
---
5+
6+
Added a mutex to synchronize compiler list downloads

v-next/hardhat-utils/src/synchronization.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
// ATTENTION: in the current implementation, there's still a risk of two processes running simultaneously.
55
// For example, if processA has locked the mutex and is running, processB will wait.
66
// During this wait, processB continuously checks the elapsed time since the mutex lock file was created.
7-
// If an excessive amount of time has passed, processB will assume ownership of the mutex to avoid stale locks.
8-
// However, there's a possibility that processB might take ownership because the mutex creation file is outdated, even though processA is still running
7+
// If an excessive amount of time has passed, processB will assume ownership of the mutex to prevent stale locks, even if processA is still running.
8+
// As a result, two processes will be running simultaneously in what is theoretically a mutex-locked section.
99

1010
import fs from "node:fs";
1111
import os from "node:os";

v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.ts

+19-16
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ export class CompilerDownloaderImplementation implements CompilerDownloader {
138138
readonly #compilersDir: string;
139139
readonly #downloadFunction: typeof download;
140140

141-
readonly #mutex = new MultiProcessMutex("compiler-download");
141+
readonly #mutexCompiler = new MultiProcessMutex("compiler-download");
142+
readonly #mutexCompilerList = new MultiProcessMutex("compiler-download-list");
142143

143144
/**
144145
* Use CompilerDownloader.getConcurrencySafeDownloader instead
@@ -156,21 +157,23 @@ export class CompilerDownloaderImplementation implements CompilerDownloader {
156157
public async updateCompilerListIfNeeded(
157158
versions: Set<string>,
158159
): Promise<void> {
159-
if (await this.#shouldDownloadCompilerList(versions)) {
160-
try {
161-
log(
162-
`Downloading the list of solc builds for platform ${this.#platform}`,
163-
);
164-
await this.#downloadCompilerList();
165-
} catch (e) {
166-
ensureError(e);
167-
168-
throw new HardhatError(
169-
HardhatError.ERRORS.SOLIDITY.VERSION_LIST_DOWNLOAD_FAILED,
170-
e,
171-
);
160+
await this.#mutexCompilerList.use(async () => {
161+
if (await this.#shouldDownloadCompilerList(versions)) {
162+
try {
163+
log(
164+
`Downloading the list of solc builds for platform ${this.#platform}`,
165+
);
166+
await this.#downloadCompilerList();
167+
} catch (e) {
168+
ensureError(e);
169+
170+
throw new HardhatError(
171+
HardhatError.ERRORS.SOLIDITY.VERSION_LIST_DOWNLOAD_FAILED,
172+
e,
173+
);
174+
}
172175
}
173-
}
176+
});
174177
}
175178

176179
public async isCompilerDownloaded(version: string): Promise<boolean> {
@@ -186,7 +189,7 @@ export class CompilerDownloaderImplementation implements CompilerDownloader {
186189
// This is because the mutex blocks access until a compiler has been fully downloaded, preventing any new process
187190
// from checking whether that version of the compiler exists. Without mutex it might incorrectly
188191
// return false, indicating that the compiler isn't present, even though it is currently being downloaded.
189-
return this.#mutex.use(async () => {
192+
return this.#mutexCompiler.use(async () => {
190193
const isCompilerDownloaded = await this.isCompilerDownloaded(version);
191194

192195
if (isCompilerDownloaded === true) {

0 commit comments

Comments
 (0)