write
write copied to clipboard
Possible race condition if 2 calls write to the same file
I think there is a race condition when 2 write() calls write to the same file at almost the same time, like the test case below:
const targetFile = path.join(os.tmpdir(), 'test.txt');
fs.rmSync(targetFile, {force: true});
const content1 = Buffer.alloc(100 * 1024 * 1024); // A will finish writing later than B
const content2 = Buffer.alloc(50 * 1024 * 1024);
crypto.randomFillSync(content1);
crypto.randomFillSync(content2);
process.on('uncaughtException', (e) =>
{
console.error(e);
});
process.on('beforeExit', () =>
{
fs.rmSync(targetFile, {force: true});
});
// A
write(targetFile, content1, {overwrite: true}, err =>
{
if (err)
{
console.error(err);
}
else
{
const targetContent = fs.readFileSync(targetFile);
assert.ok(targetContent.equals(content1), `The content of targetFile is not content1!`);
}
});
// B
write(targetFile, content2, {overwrite: true}, err =>
{
if (err)
{
console.error(err);
}
else
{
const targetContent = fs.readFileSync(targetFile);
assert.ok(targetContent.equals(content2), `The content of targetFile is not content2!`);
}
});
And the execution result is:
AssertionError [ERR_ASSERTION]: The content of targetFile is not content2!
...
AssertionError [ERR_ASSERTION]: The content of targetFile is not content1!
...
targetFile may become a corrupted file with content different from either content1 or content2.
I think the bug is caused by the use of stream:
https://github.com/jonschlinkert/write/blob/f537eb68091d0257b5a4ea915aa00a2c46727198/index.js#L58-L61
Both A and B can create write streams and write to targetFile at the same time. I think write() should check whether a file is being written before writing to it.