Skip to content

Commit 02e5c12

Browse files
committed
fix(arborist): retry bin-links on Windows EPERM during linked strategy install
On Windows, antivirus and search indexer can transiently lock files, causing write-file-atomic's fs.rename to fail with EPERM during the bin-linking phase. The linked strategy amplifies this by writing many store entries in parallel. Add retry with backoff (up to 5 attempts) for EPERM/EACCES/EBUSY errors in #createBinLinks, Windows only.
1 parent 4426411 commit 02e5c12

1 file changed

Lines changed: 25 additions & 7 deletions

File tree

workspaces/arborist/lib/arborist/rebuild.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -381,18 +381,36 @@ module.exports = cls => class Builder extends cls {
381381

382382
const timeEnd = time.start(`build:link:${node.location}`)
383383

384-
const p = binLinks({
385-
pkg: node.package,
386-
path: node.path,
387-
top: !!(node.isTop || node.globalTop),
388-
force: this.options.force,
389-
global: !!node.globalTop,
390-
})
384+
const p = this.#binLinksWithRetry(node)
391385

392386
await (this.#doHandleOptionalFailure
393387
? this[_handleOptionalFailure](node, p)
394388
: p)
395389

396390
timeEnd()
397391
}
392+
393+
// On Windows, antivirus/indexer can transiently lock files, causing
394+
// EPERM/EACCES/EBUSY on the rename inside write-file-atomic (used by
395+
// bin-links/fix-bin.js). Retry with backoff for up to 10 seconds.
396+
async #binLinksWithRetry (node, retries = 5) {
397+
try {
398+
return await binLinks({
399+
pkg: node.package,
400+
path: node.path,
401+
top: !!(node.isTop || node.globalTop),
402+
force: this.options.force,
403+
global: !!node.globalTop,
404+
})
405+
} catch (err) {
406+
if (process.platform === 'win32' &&
407+
retries > 0 &&
408+
(err.code === 'EPERM' || err.code === 'EACCES' || err.code === 'EBUSY')) {
409+
const delay = (6 - retries) * 500
410+
await new Promise(r => setTimeout(r, delay))
411+
return this.#binLinksWithRetry(node, retries - 1)
412+
}
413+
throw err
414+
}
415+
}
398416
}

0 commit comments

Comments
 (0)