From a24ee0b35a9c8e0ad7130dcb73c99dbe6b5dfdb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Rzepecki?= Date: Thu, 22 May 2025 16:16:36 +0200 Subject: [PATCH] fix: Avoid EEXIST on race condition in createDirRecursively and copyFolderRecursiveSync Replace custom recursive directory creation with built-in recursive mkdir in node addon loading When multiple packaged applications try to start simultaneously, they can encounter race conditions when creating temporary directories for loading native node addons. This manifests as an "EEXIST" error when calling `mkdirSync()`. The issue occurs in the native module loading code path where pkg needs to extract native addons to a temporary location before they can be loaded via `process.dlopen()`. The current implementation uses a custom `createDirRecursively()` function that has a race condition - it checks if a directory exists and then tries to create it, but another process could create the directory between the check and creation. Node.js has built-in support for recursive directory creation via the `recursive: true` option in `mkdirSync()`. This handles race conditions properly - if the directory already exists, it will not throw an error. This is exactly what we need. --- prelude/bootstrap.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/prelude/bootstrap.js b/prelude/bootstrap.js index 5fc3ee63..89232cfb 100644 --- a/prelude/bootstrap.js +++ b/prelude/bootstrap.js @@ -185,9 +185,7 @@ function copyFolderRecursiveSync(source, target) { const targetFolder = path.join(target, path.basename(source)); // Check if target folder needs to be created or integrated - if (!fs.existsSync(targetFolder)) { - fs.mkdirSync(targetFolder); - } + fs.mkdirSync(targetFolder, { recursive: true }); // Copy if (fs.lstatSync(source).isDirectory()) { @@ -249,13 +247,6 @@ function copyFolderRecursiveSync(source, target) { } } -function createDirRecursively(dir) { - if (!fs.existsSync(dir)) { - createDirRecursively(path.join(dir, '..')); - fs.mkdirSync(dir); - } -} - /* // TODO move to some test @@ -2218,7 +2209,7 @@ function payloadFileSync(pointer) { // Example: /home/john/.cache/pkg/ const tmpFolder = path.join(homedir(), '.cache/pkg', hash); - createDirRecursively(tmpFolder); + fs.mkdirSync(tmpFolder, { recursive: true }); // Example: moduleFolder = /snapshot/appname/node_modules/sharp/build/Release const parts = moduleFolder.split(path.sep);