Version
v24.17.0
Platform
Microsoft Windows NT 10.0.26200.0 x64
Subsystem
fs
What steps will reproduce the bug?
Given that the current workspace looks like this: (just for reference on how the minimal reproducible were structured)
eperm-folder
|---> locked-file.txt
locking.py
index.js
locking.py
import os, signal
os.makedirs("eperm-folder", exist_ok=True)
filepath = "eperm-folder/locked-file.txt"
print(f"locking {filepath} indefinitely, until SIGINT")
fd = os.open(filepath, os.O_RDWR | os.O_CREAT )
os.write(fd, b'Hello, World!')
def sigterm_handler(s, f):
os.close(fd)
exit(0)
signal.signal(signal.SIGINT, sigterm_handler)
while True:
pass
index.js
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
const path = require('node:path')
const { spawn } = require('node:child_process')
const filepath = "eperm-folder/locked-file.txt"
if (fs.existsSync(filepath)) {
console.log('deleting eperm-folder/')
const start = performance.now()
try {
fs.rmSync(path.dirname(filepath), { recursive: true, retryDelay: 5 * 1000, maxRetries: 1 })
}
catch (e){
console.log(e)
const duration = performance.now() - start;
console.log(`rmSync - ${duration} ms`)
}
}
Steps to run:
- Run
python locking.py first to create eperm-folder/locked-file.txt and to indefinitely lock it (this is to simulate an EPERM/EBUSY error)
- Then run
node index.js
How often does it reproduce? Is there a required condition?
Always if the directory / file being deleted is locked by another process.
What is the expected behavior? Why is that the expected behavior?
The time elapsed should be around 15,000ms, since the given retryDelay is 5000 (ms), the time elapsed shouldn't be less than 5000ms
For comparison, in the asynchronous fs.rm functions, the time elapsed is around 15,000ms which is what expected
Here's a reproducible script for the asynchronous fs.rm functions
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
const path = require('node:path')
const filepath = "eperm-folder/locked-file.txt"
if (fs.existsSync(filepath)) {
console.log('deleting eperm-folder/')
const start = performance.now()
fs.rm(
path.dirname(filepath),
{ recursive: true, retryDelay: 5 * 1000, maxRetries: 1 },
(e) => {
if (e)
console.error(e)
const duration = performance.now() - start;
console.log(`async fs.rm() - ${duration} ms`)
}
)
}
This means that in the fs.rmSync, retries are not delayed
What do you see instead?
The time elapsed in the fs.rmSync operation is between 1-30 ms (on my end)
Additional information
This affects other retryable errors in Windows (e.g., EMFILE, ENFILE, ENOTEMPTY)
Might be related to #55555, but this is Windows-specific
Version
v24.17.0
Platform
Subsystem
fs
What steps will reproduce the bug?
Given that the current workspace looks like this: (just for reference on how the minimal reproducible were structured)
locking.pyindex.jsSteps to run:
python locking.pyfirst to createeperm-folder/locked-file.txtand to indefinitely lock it (this is to simulate anEPERM/EBUSYerror)node index.jsHow often does it reproduce? Is there a required condition?
Always if the directory / file being deleted is locked by another process.
What is the expected behavior? Why is that the expected behavior?
The time elapsed should be around
15,000ms, since the givenretryDelayis5000(ms), the time elapsed shouldn't be less than5000msFor comparison, in the asynchronous
fs.rmfunctions, the time elapsed is around15,000mswhich is what expectedHere's a reproducible script for the asynchronous
fs.rmfunctionsThis means that in the
fs.rmSync, retries are not delayedWhat do you see instead?
The time elapsed in the
fs.rmSyncoperation is between1-30 ms(on my end)Additional information
This affects other retryable errors in Windows (e.g.,
EMFILE,ENFILE,ENOTEMPTY)Might be related to #55555, but this is Windows-specific