Skip to content

Instantly share code, notes, and snippets.

@hunterloftis
Last active October 15, 2021 16:16
Show Gist options
  • Save hunterloftis/e3b908ade0226556459bc954877c493d to your computer and use it in GitHub Desktop.
Save hunterloftis/e3b908ade0226556459bc954877c493d to your computer and use it in GitHub Desktop.
// node clobber.mjs -> demonstrate common filesystem anti-pattern that creates race conditions
// node clobber.mjs safe -> demonstrate safe filesystem manipulation
import cluster from 'cluster';
import process from 'process';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const concurrency = 100;
const directory = path.resolve(__dirname, 'foobar');
const safe = process.argv[2] === 'safe';
const createDir = safe ? createDirSafely : createDirUnsafely;
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running, safe?`, safe);
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
process.exit(1);
});
setTimeout(() => {
for (let i = 0; i < concurrency; i++) cluster.fork();
}, 1000);
}
else {
setInterval(() => {
Math.random() < 0.5 ? createDir() : destroyDir();
}, 100);
}
function createDirUnsafely() {
// this appears to guarantee that the directory doesn't exist,
// but it's not possible to hold that guarantee through to the subsequent write
if (fs.existsSync(directory)) return;
fs.mkdirSync(directory);
console.log('created directory');
}
function createDirSafely() {
try {
// notice that no exists check is necessary
fs.mkdirSync(directory, { recursive: true });
console.log('created directory');
} catch (err) {
console.log('failed to create directory');
}
}
function destroyDir() {
try {
fs.rmSync(directory, { recursive: true });
} catch (err) {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment