-
Notifications
You must be signed in to change notification settings - Fork 8
Open
Description
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:
Lines 58 to 61 in f537eb6
| fs.createWriteStream(destpath, opts) | |
| .on('error', err => reject(err)) | |
| .on('close', resolve) | |
| .end(ensureNewline(data, opts)); |
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.
Metadata
Metadata
Assignees
Labels
No labels