module: compile cache leaks temporary files when persistence fails
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- JavaScript
- Sterne
- 122k
- Forks
- 37.3k
- Ø Merge
- 4 T. 2 Std.
- Gemergte PRs (30 T.)
- 283
Beschreibung
Version
v24.15.0
Platform
Linux pike 7.0.0-29-generic #29-Ubuntu SMP PREEMPT_DYNAMIC Fri Jul 17 20:52:35 UTC 2026 x86_64 GNU/Linux
Subsystem
module compile cache
What steps will reproduce the bug?
This uses RLIMIT_FSIZE=0 to make mkstemp() succeed and the subsequent write fail. It requires no third-party dependencies or elevated privileges.
tmp="$(mktemp -d)"
mkdir -p "$tmp/cache"
printf '%s\n' 'module.exports = 42;' >"$tmp/fixture.cjs"
(
cd "$tmp"
ulimit -f 0
trap '' XFSZ
NODE_COMPILE_CACHE="$tmp/cache" node -e "require('./fixture.cjs')"
)
find "$tmp/cache" -type f -printf '%P %s bytes\n'
Example output:
v24.15.0-x64-cf738c9d-1000/712488c2.LuhsmB 0 bytes
v24.15.0-x64-cf738c9d-1000/8e9c99c2.hwlSas 0 bytes
v24.15.0-x64-cf738c9d-1000/9fb526e9.wPP9zO 0 bytes
The Node process exits with status 0.
How often does it reproduce? Is there a required condition?
Every run on the Linux system above. The required condition is that creation of the temporary cache file succeeds but a later write, close, or rename fails. EDQUOT, ENOSPC, and EFBIG are representative failure modes.
What is the expected behavior? Why is that the expected behavior?
The compile cache should continue to fail gracefully, but it should close the temporary file descriptor and unlink the temporary file whenever persistence does not complete. A failed cache write is disposable internal state and should not consume additional filesystem space or inodes.
What do you see instead?
Each failed entry leaves its random-suffix temporary file in the compile-cache directory. On the write-error path, its file descriptor also remains open until process teardown.
In a real EDQUOT incident, one Node process left 3,424 zero-byte compile-cache temporary files in one minute. This amplified a block-quota failure into substantial inode consumption.
Additional information
Current main creates the temporary file, then immediately continues on write, close, or rename errors without unlinking it:
The same control flow is present in v24.15.0.
A possible fix is an RAII cleanup guard established immediately after successful uv_fs_mkstemp() that:
- closes the descriptor if it is still open;
- unlinks the temporary path unless the rename succeeded;
- is disarmed only after successful rename;
- preserves the original persistence error.
A regression test can use the same RLIMIT_FSIZE technique on supported POSIX platforms and assert that no random-suffix temporary files remain.
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginnen Sie in src/compile_cache.cc um die Zeilen 478–516 und führen Sie die bereitgestellte RLIMIT_FSIZE-Reproduktion aus, um die Verarbeitung temporärer Dateien über Fehler bei write, close und rename hinweg nachzuverfolgen. Fügen Sie auf unterstützten POSIX-Plattformen einen Regressionstest hinzu, der verifiziert, dass eine fehlgeschlagene Persistenz keine temporären Dateien mit zufälligem Suffix hinterlässt. Die Aufgabe ist erledigt, wenn fehlgeschlagene Cache-Schreibvorgänge Dateideskriptoren schließen, temporäre Pfade entfernen und das kontrollierte Fehlschlagen des Caches beibehalten.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- cpp, javascript, nodejs
- Bereich
- backend, performance, testing
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Aktiv
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 74/100