Skip to content

Commit 71f697d

Browse files
committed
bootstrap: ensure a unique temp folder for each process
1 parent 193b778 commit 71f697d

1 file changed

Lines changed: 64 additions & 40 deletions

File tree

prelude/bootstrap.js

Lines changed: 64 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
'use strict';
1818

1919
const childProcess = require('child_process');
20-
const { createHash } = require('crypto');
20+
const { randomFillSync } = require('crypto');
2121
const fs = require('fs');
2222
const { isRegExp } = require('util').types;
2323
const Module = require('module');
@@ -213,6 +213,44 @@ function createDirRecursively(dir) {
213213
}
214214
}
215215

216+
function removeDirRecursively(dir) {
217+
if (fs.existsSync(dir)) {
218+
fs.readdirSync(dir).forEach((file) => {
219+
const curPath = path.join(dir, file);
220+
if (fs.lstatSync(curPath).isDirectory()) {
221+
removeDirRecursively(curPath);
222+
} else {
223+
fs.unlinkSync(curPath);
224+
}
225+
});
226+
fs.rmdirSync(dir);
227+
}
228+
}
229+
230+
const tmpFolder = (() => {
231+
const buf = Buffer.alloc(16);
232+
randomFillSync(buf);
233+
return path.join(tmpdir(), 'pkg', `${process.pid}.${buf.toString('hex')}`);
234+
})();
235+
236+
function removeTemporaryFolderAndContent(folder) {
237+
if (!folder) return;
238+
239+
if (!fs.existsSync(folder)) {
240+
return;
241+
}
242+
243+
if (NODE_VERSION_MAJOR <= 10) {
244+
return removeDirRecursively(folder);
245+
}
246+
247+
if (NODE_VERSION_MAJOR <= 14) {
248+
return fs.rmdirSync(folder, { recursive: true });
249+
}
250+
251+
return fs.rmSync(folder, { recursive: true });
252+
}
253+
216254
/*
217255
218256
// TODO move to some test
@@ -644,37 +682,23 @@ function payloadFileSync(pointer) {
644682
// open //////////////////////////////////////////////////////////
645683
// ///////////////////////////////////////////////////////////////
646684

647-
function removeTemporaryFolderAndContent(folder) {
648-
if (!folder) return;
649-
if (NODE_VERSION_MAJOR <= 14) {
650-
if (NODE_VERSION_MAJOR <= 10) {
651-
// folder must be empty
652-
for (const f of fs.readdirSync(folder)) {
653-
fs.unlinkSync(path.join(folder, f));
654-
}
655-
fs.rmdirSync(folder);
656-
} else {
657-
fs.rmdirSync(folder, { recursive: true });
658-
}
659-
} else {
660-
fs.rmSync(folder, { recursive: true });
661-
}
662-
}
663685
const temporaryFiles = {};
664-
const os = require('os');
665-
let tmpFolder = '';
686+
666687
process.on('beforeExit', () => {
667688
removeTemporaryFolderAndContent(tmpFolder);
668689
});
690+
669691
function deflateSync(snapshotFilename) {
670-
if (!tmpFolder) {
671-
tmpFolder = fs.mkdtempSync(path.join(os.tmpdir(), 'pkg-'));
672-
}
673692
const content = fs.readFileSync(snapshotFilename, { encoding: 'binary' });
674-
// content is already unzipped !
693+
const fName = path.join(
694+
tmpFolder,
695+
process.platform === 'win32'
696+
? findVirtualFileSystemKeyAndFollowLinks(snapshotFilename).slice(2)
697+
: findVirtualFileSystemKeyAndFollowLinks(snapshotFilename)
698+
);
699+
700+
createDirRecursively(path.dirname(fName));
675701

676-
const hash = createHash('sha256').update(content).digest('hex');
677-
const fName = path.join(tmpFolder, hash);
678702
fs.writeFileSync(fName, content, 'binary');
679703
return fName;
680704
}
@@ -2160,18 +2184,6 @@ function payloadFileSync(pointer) {
21602184
const moduleFolder = path.dirname(modulePath);
21612185

21622186
if (insideSnapshot(modulePath)) {
2163-
const moduleContent = fs.readFileSync(modulePath);
2164-
2165-
// Node addon files and .so cannot be read with fs directly, they are loaded with process.dlopen which needs a filesystem path
2166-
// we need to write the file somewhere on disk first and then load it
2167-
// the hash is needed to be sure we reload the module in case it changes
2168-
const hash = createHash('sha256').update(moduleContent).digest('hex');
2169-
2170-
// Example: /tmp/pkg/<hash>
2171-
const tmpFolder = path.join(tmpdir(), 'pkg', hash);
2172-
2173-
createDirRecursively(tmpFolder);
2174-
21752187
// Example: moduleFolder = /snapshot/appname/node_modules/sharp/build/Release
21762188
const parts = moduleFolder.split(path.sep);
21772189
const mIndex = parts.indexOf('node_modules') + 1;
@@ -2181,6 +2193,8 @@ function payloadFileSync(pointer) {
21812193
// it's a node addon file contained in node_modules folder
21822194
// we copy the entire module folder in tmp folder
21832195
if (mIndex > 0) {
2196+
createDirRecursively(path.join(tmpFolder, 'node_modules'));
2197+
21842198
// Example: modulePackagePath = sharp/build/Release
21852199
const modulePackagePath = parts.slice(mIndex).join(path.sep);
21862200
// Example: modulePkgFolder = /snapshot/appname/node_modules/sharp
@@ -2189,11 +2203,21 @@ function payloadFileSync(pointer) {
21892203
// here we copy all files from the snapshot module folder to temporary folder
21902204
// we keep the module folder structure to prevent issues with modules that are statically
21912205
// linked using relative paths (Fix #1075)
2192-
copyFolderRecursiveSync(modulePkgFolder, tmpFolder);
2206+
copyFolderRecursiveSync(
2207+
modulePkgFolder,
2208+
path.join(tmpFolder, 'node_modules')
2209+
);
21932210

2194-
// Example: /tmp/pkg/<hash>/sharp/build/Release/sharp.node
2195-
newPath = path.join(tmpFolder, modulePackagePath, moduleBaseName);
2211+
// Example: /tmp/pkg/<hash>/node_modules/sharp/build/Release/sharp.node
2212+
newPath = path.join(
2213+
tmpFolder,
2214+
'node_modules',
2215+
modulePackagePath,
2216+
moduleBaseName
2217+
);
21962218
} else {
2219+
createDirRecursively(tmpFolder);
2220+
21972221
const tmpModulePath = path.join(tmpFolder, moduleBaseName);
21982222

21992223
if (!fs.existsSync(tmpModulePath)) {

0 commit comments

Comments
 (0)