Skip to content

Commit

Permalink
fs: fix busy loop in recursive rm for windows
Browse files Browse the repository at this point in the history
  • Loading branch information
RaisinTen committed Mar 1, 2021
1 parent e6cbec5 commit 7f0eccd
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/internal/fs/rimraf.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ function _rmdirSync(path, options, originalErr) {
} catch (err) {
if (err.code === 'ENOENT')
return;
if (err.code === 'ENOTDIR')
if (err.code === 'EACCES' || err.code === 'ENOTDIR')
throw originalErr;

if (notEmptyErrorCodes.has(err.code)) {
Expand Down
44 changes: 44 additions & 0 deletions test/parallel/test-recursive-rm-busy-loop-windows.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict';
require('../common');

// This test ensures that recursive rm throws EACCES instead of
// going into a busy-loop for this scenario:
// https://github.com/nodejs/node/issues/34580

const assert = require('assert');
const fs = require('fs');
const tmpdir = require('../common/tmpdir');
const { join } = require('path');

tmpdir.refresh();

function rmdirRecursiveSync() {
const root = fs.mkdtempSync(tmpdir.path);

const middle = join(root, 'middle');
fs.mkdirSync(middle);
fs.mkdirSync(join(middle, 'leaf')); // Make `middle` non-empty
fs.chmodSync(middle, 0);

// Windows can EPERM on stat, which is called inside rmdirSync.
let runTest = false;
try {
fs.statSync(middle);
runTest = true;
} catch (err) {
assert.strictEqual(err.code, 'EPERM');
} finally {
try {
if (runTest) {
assert.throws(() => {
fs.rmSync(root, { recursive: true });
}, /EACCES/);
}
} finally {
fs.chmodSync(middle, 0o777);
fs.rmdirSync(root, { recursive: true });
}
}
}

rmdirRecursiveSync();

0 comments on commit 7f0eccd

Please sign in to comment.