Skip to content

Commit a7f00e3

Browse files
Nitzan UzielyLinkgoron
authored andcommitted
fs: fix writeFile signal does not close file
Fix an issue where the writeFile does not close the file when the signal is aborted
1 parent 88d9268 commit a7f00e3

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

lib/fs.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ function readFile(path, options, callback) {
338338
return;
339339
}
340340

341+
if (options.signal?.aborted) {
342+
callback(lazyDOMException('The operation was aborted', 'AbortError'));
343+
return;
344+
}
345+
341346
const flagsNumber = stringToFlags(options.flag);
342347
path = getValidatedPath(path);
343348

@@ -1448,7 +1453,13 @@ function lutimesSync(path, atime, mtime) {
14481453

14491454
function writeAll(fd, isUserFd, buffer, offset, length, signal, callback) {
14501455
if (signal?.aborted) {
1451-
callback(lazyDOMException('The operation was aborted', 'AbortError'));
1456+
if (isUserFd) {
1457+
callback(lazyDOMException('The operation was aborted', 'AbortError'));
1458+
} else {
1459+
fs.close(fd, function() {
1460+
callback(lazyDOMException('The operation was aborted', 'AbortError'));
1461+
});
1462+
}
14521463
return;
14531464
}
14541465
// write(fd, buffer, offset, length, position, callback)

test/parallel/test-fs-write-file.js

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ const common = require('../common');
2424
const assert = require('assert');
2525
const fs = require('fs');
2626
const join = require('path').join;
27-
27+
const cp = require('child_process');
28+
const os = require('os');
2829
const tmpdir = require('../common/tmpdir');
30+
2931
tmpdir.refresh();
3032

3133
const filename = join(tmpdir.path, 'test.txt');
@@ -67,31 +69,60 @@ fs.open(filename4, 'w+', common.mustSucceed((fd) => {
6769
}));
6870
}));
6971

72+
function checkIfFileIsOpen(fileName) {
73+
const platform = os.platform();
74+
if (platform === 'linux' || platform === 'darwin') {
75+
// Tried other ways like rm/stat, but that didn't work.
76+
cp.exec(`lsof -p ${process.pid}`, common.mustCall((err, value) => {
77+
if (err) {
78+
assert.ifError(err);
79+
return;
80+
}
81+
assert.ok(!value.toString().includes(fileName),
82+
`${fileName} is still open, but should be closed`);
83+
}));
84+
}
85+
}
7086

7187
{
7288
// Test that writeFile is cancellable with an AbortSignal.
73-
// Before the operation has started
89+
// abort sync after the operation has started
7490
const controller = new AbortController();
7591
const signal = controller.signal;
7692
const filename3 = join(tmpdir.path, 'test3.txt');
7793

7894
fs.writeFile(filename3, s, { signal }, common.mustCall((err) => {
7995
assert.strictEqual(err.name, 'AbortError');
96+
checkIfFileIsOpen(filename3);
8097
}));
8198

8299
controller.abort();
83100
}
84101

85102
{
86103
// Test that writeFile is cancellable with an AbortSignal.
87-
// After the operation has started
104+
// abort async after the operation has started
88105
const controller = new AbortController();
89106
const signal = controller.signal;
90-
const filename4 = join(tmpdir.path, 'test5.txt');
107+
const filename5 = join(tmpdir.path, 'test5.txt');
91108

92-
fs.writeFile(filename4, s, { signal }, common.mustCall((err) => {
109+
fs.writeFile(filename5, s, { signal }, common.mustCall((err) => {
93110
assert.strictEqual(err.name, 'AbortError');
111+
checkIfFileIsOpen(filename5);
94112
}));
95113

96114
process.nextTick(() => controller.abort());
97115
}
116+
117+
{
118+
// Test that writeFile is cancellable with an AbortSignal.
119+
// abort before the operation has started
120+
const controller = new AbortController();
121+
const signal = controller.signal;
122+
const filename6 = join(tmpdir.path, 'test6.txt');
123+
controller.abort();
124+
fs.writeFile(filename6, s, { signal }, common.mustCall((err) => {
125+
assert.strictEqual(err.name, 'AbortError');
126+
checkIfFileIsOpen(filename6);
127+
}));
128+
}

0 commit comments

Comments
 (0)