Skip to content

Commit

Permalink
bootstrap: ensure a unique temp folder for each process
Browse files Browse the repository at this point in the history
  • Loading branch information
jesec committed May 8, 2022
1 parent 193b778 commit 71f697d
Showing 1 changed file with 64 additions and 40 deletions.
104 changes: 64 additions & 40 deletions prelude/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
'use strict';

const childProcess = require('child_process');
const { createHash } = require('crypto');
const { randomFillSync } = require('crypto');
const fs = require('fs');
const { isRegExp } = require('util').types;
const Module = require('module');
Expand Down Expand Up @@ -213,6 +213,44 @@ function createDirRecursively(dir) {
}
}

function removeDirRecursively(dir) {
if (fs.existsSync(dir)) {
fs.readdirSync(dir).forEach((file) => {
const curPath = path.join(dir, file);
if (fs.lstatSync(curPath).isDirectory()) {
removeDirRecursively(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(dir);
}
}

const tmpFolder = (() => {
const buf = Buffer.alloc(16);
randomFillSync(buf);
return path.join(tmpdir(), 'pkg', `${process.pid}.${buf.toString('hex')}`);
})();

function removeTemporaryFolderAndContent(folder) {
if (!folder) return;

if (!fs.existsSync(folder)) {
return;
}

if (NODE_VERSION_MAJOR <= 10) {
return removeDirRecursively(folder);
}

if (NODE_VERSION_MAJOR <= 14) {
return fs.rmdirSync(folder, { recursive: true });
}

return fs.rmSync(folder, { recursive: true });
}

/*
// TODO move to some test
Expand Down Expand Up @@ -644,37 +682,23 @@ function payloadFileSync(pointer) {
// open //////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////////////

function removeTemporaryFolderAndContent(folder) {
if (!folder) return;
if (NODE_VERSION_MAJOR <= 14) {
if (NODE_VERSION_MAJOR <= 10) {
// folder must be empty
for (const f of fs.readdirSync(folder)) {
fs.unlinkSync(path.join(folder, f));
}
fs.rmdirSync(folder);
} else {
fs.rmdirSync(folder, { recursive: true });
}
} else {
fs.rmSync(folder, { recursive: true });
}
}
const temporaryFiles = {};
const os = require('os');
let tmpFolder = '';

process.on('beforeExit', () => {
removeTemporaryFolderAndContent(tmpFolder);
});

function deflateSync(snapshotFilename) {
if (!tmpFolder) {
tmpFolder = fs.mkdtempSync(path.join(os.tmpdir(), 'pkg-'));
}
const content = fs.readFileSync(snapshotFilename, { encoding: 'binary' });
// content is already unzipped !
const fName = path.join(
tmpFolder,
process.platform === 'win32'
? findVirtualFileSystemKeyAndFollowLinks(snapshotFilename).slice(2)
: findVirtualFileSystemKeyAndFollowLinks(snapshotFilename)
);

createDirRecursively(path.dirname(fName));

const hash = createHash('sha256').update(content).digest('hex');
const fName = path.join(tmpFolder, hash);
fs.writeFileSync(fName, content, 'binary');
return fName;
}
Expand Down Expand Up @@ -2160,18 +2184,6 @@ function payloadFileSync(pointer) {
const moduleFolder = path.dirname(modulePath);

if (insideSnapshot(modulePath)) {
const moduleContent = fs.readFileSync(modulePath);

// Node addon files and .so cannot be read with fs directly, they are loaded with process.dlopen which needs a filesystem path
// we need to write the file somewhere on disk first and then load it
// the hash is needed to be sure we reload the module in case it changes
const hash = createHash('sha256').update(moduleContent).digest('hex');

// Example: /tmp/pkg/<hash>
const tmpFolder = path.join(tmpdir(), 'pkg', hash);

createDirRecursively(tmpFolder);

// Example: moduleFolder = /snapshot/appname/node_modules/sharp/build/Release
const parts = moduleFolder.split(path.sep);
const mIndex = parts.indexOf('node_modules') + 1;
Expand All @@ -2181,6 +2193,8 @@ function payloadFileSync(pointer) {
// it's a node addon file contained in node_modules folder
// we copy the entire module folder in tmp folder
if (mIndex > 0) {
createDirRecursively(path.join(tmpFolder, 'node_modules'));

// Example: modulePackagePath = sharp/build/Release
const modulePackagePath = parts.slice(mIndex).join(path.sep);
// Example: modulePkgFolder = /snapshot/appname/node_modules/sharp
Expand All @@ -2189,11 +2203,21 @@ function payloadFileSync(pointer) {
// here we copy all files from the snapshot module folder to temporary folder
// we keep the module folder structure to prevent issues with modules that are statically
// linked using relative paths (Fix #1075)
copyFolderRecursiveSync(modulePkgFolder, tmpFolder);
copyFolderRecursiveSync(
modulePkgFolder,
path.join(tmpFolder, 'node_modules')
);

// Example: /tmp/pkg/<hash>/sharp/build/Release/sharp.node
newPath = path.join(tmpFolder, modulePackagePath, moduleBaseName);
// Example: /tmp/pkg/<hash>/node_modules/sharp/build/Release/sharp.node
newPath = path.join(
tmpFolder,
'node_modules',
modulePackagePath,
moduleBaseName
);
} else {
createDirRecursively(tmpFolder);

const tmpModulePath = path.join(tmpFolder, moduleBaseName);

if (!fs.existsSync(tmpModulePath)) {
Expand Down

0 comments on commit 71f697d

Please sign in to comment.