Skip to content

Tests: temporäre Verzeichnisse aller Testdateien beim Prozessende aufräumen - #235

Merged
CallMeTechie merged 1 commit into
masterfrom
fix/test-tmpdir-leak
Jul 27, 2026
Merged

Tests: temporäre Verzeichnisse aller Testdateien beim Prozessende aufräumen#235
CallMeTechie merged 1 commit into
masterfrom
fix/test-tmpdir-leak

Conversation

@CallMeTechie

Copy link
Copy Markdown
Owner

Aufgefallen, weil /tmp mitten in der Arbeit zu 100 % volllief (3,9 GB) und Kommandos nicht einmal mehr ihre Ausgabe schreiben konnten. Ursache waren nicht etwa große Dateien, sondern 3.667 zurückgelassene Testverzeichnisse.

Befund

70 Testdateien legen mit fs.mkdtempSync ein temporäres Verzeichnis an — jede mit eigenem Präfix (gc-caddy-retry-, gc-cc-contract-, gc-env-, gc-del-guard- …). 59 davon entfernen es nie.

Gemessen, nicht geschätzt:

ohne Fix:  65 zurückgelassene Verzeichnisse pro Suite-Lauf
mit Fix:    0

Bei rund 56 Läufen summierte sich das auf 3.667 Einträge. Das Tückische ist nicht der Platz, sondern die Symptomlage: ein volles /tmp äußert sich in Fehlern ohne jeden Bezug zu Tests.

Bemerkenswert ist, dass das Problem in diesem Repo schon einmal erkannt wurde: tests/helpers/setup.js räumt sein eigenes Verzeichnis beim Prozessende ab und hat sogar einen Selbstheilungs-Sweep für hart abgebrochene Läufe — mit einem Kommentar, der genau diese Begründung nennt. Beides greift aber ausschließlich für das Präfix gc-test- dieser einen Datei.

Nicht betroffen: der Produktivcode. src/ und scripts/ rufen mkdtempSync nirgends auf — das ist ein reines Problem der Testumgebung, kein Produktfehler.

Änderung

Statt 59 Dateien einzeln nachzurüsten — und die nächste neue Datei wieder zu vergessen — wird mkdtempSync einmal zentral umhüllt: tests/helpers/tmp-cleanup.js merkt sich die angelegten Verzeichnisse und entfernt sie beim Prozessende.

Vorgeladen über --require im test-Skript, damit es jeden Testprozess erreicht, auch die 59 Dateien, die keinen gemeinsamen Helfer verwenden. Zusätzlich aus tests/helpers/setup.js heraus geladen, damit auch ein direkter Einzeldatei-Lauf ohne npm aufräumt; der require-Cache sorgt dafür, dass die Umhüllung nur einmal greift.

Dass --require bis in die Kindprozesse des Test-Runners durchschlägt, habe ich empirisch geprüft, nicht angenommen.

Zwei Schutzmaßnahmen im Wrapper: es wird nur entfernt, was tatsächlich unterhalb von os.tmpdir() liegt (über realpath aufgelöst, damit auch der macOS-Symlink /tmp/private/tmp greift), und ein Fehler beim Aufräumen lässt einen Testlauf niemals scheitern.

Tests

Sechs neue Fälle, angehängt an die vorhandene tests/tmp_cleanup.test.js (die bisher nur den gc-test--Sweeper abdeckte). Geprüft wird die Eigenschaft, nicht die Aufrufliste: ein Kindprozess legt ein Verzeichnis mitsamt Inhalt an, und danach ist es weg.

Darunter ausdrücklich der Negativfall — ohne Vorladen überlebt das Verzeichnis. Ohne diesen Fall würde der Test auch dann grün bleiben, wenn die Umhüllung gar nichts täte.

Dazu: nicht-leere Verzeichnisse werden entfernt (ein rmSync ohne recursive scheiterte hier), Verzeichnisse außerhalb des Temp-Wurzelverzeichnisses bleiben unangetastet, mkdtempSync verhält sich während des Laufs unverändert, und das test-Skript enthält das Vorladen — ohne diesen Eintrag greift die Bereinigung im Suite-Lauf nicht, und genau der hat /tmp gefüllt.

Volle Suite über npm test: 2349 bestanden, 0 fehlgeschlagen, Temp-Bilanz ±0.

Nicht enthalten

Die 59 Testdateien bleiben unverändert. Ihre mkdtempSync-Aufrufe sind nicht falsch — es fehlte nur das Gegenstück, und das gehört an eine Stelle statt an neunundfünfzig.

@CallMeTechie
CallMeTechie merged commit 3756ef6 into master Jul 27, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant