Version
v24.17.0
Platform
Microsoft Windows NT 10.0.26200.0 x64
Subsystem
fs
What steps will reproduce the bug?
The current workspace
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
- this is to create
eperm-folder/locked-file.txt and to indefinitely lock the file (simulating an EPERM/EBUSY error)
- Then run
node index.js
How often does it reproduce? Is there a required condition?
Always, this is specific to Windows, and only when the file / directory is locked by another process.
What is the expected behavior? Why is that the expected behavior?
The time elapsed should be more than 5000ms given it is our retryDelay value
For comparison, in the asynchronous fs.rm functions, the time elapsed is around 15,000ms which is what we expect
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?
The current workspace
locking.pyindex.jsSteps to run:
python locking.pyfirsteperm-folder/locked-file.txtand to indefinitely lock the file (simulating anEPERM/EBUSYerror)node index.jsHow often does it reproduce? Is there a required condition?
Always, this is specific to Windows, and only when the file / directory is locked by another process.
What is the expected behavior? Why is that the expected behavior?
The time elapsed should be more than
5000msgiven it is ourretryDelayvalueFor comparison, in the asynchronous
fs.rmfunctions, the time elapsed is around15,000mswhich is what we expectHere'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