You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[P3] Compress temp files in os.TempDir() not cleaned on atelet crash — /tmp fills up #615
Severity: P3 (slow disk leak in /tmp; accelerates ENOSPC via ISSUE-007) Component: Node Layer — cmd/atelet/internal/ategcs/objects.go Audit ID: NL-9
Summary
sendBufferedZstd (used for S3/non-streaming GCS uploads) creates a temp file via os.CreateTemp("", "substrate-upload-compress-") in os.TempDir() (typically /tmp).
The deferred os.Remove cleanup only runs if the process exits normally. A SIGKILL
(OOM kill, node restart, crash) leaves potentially multi-GiB temp files in /tmp.
There is no startup sweep to clean these up. Repeated crashes during large checkpoint
uploads can exhaust /tmp.
funcsendBufferedZstd(ctx context.Context, ...) error {
tmpFile, err:=os.CreateTemp("", "substrate-upload-compress-")
iferr!=nil { returnerr }
deferos.Remove(tmpFile.Name()) // ← NOT called on SIGKILL// Write compressed data to tmpFile (may be hundreds of MB)// Upload tmpFile to S3/GCSreturnnil
}
No code in atelet/main.go's startup path sweeps for leftover substrate-upload-compress-*
files.
Steps to Reproduce
# Start a large checkpoint upload (use a big actor snapshot)
kubectl ate suspend actor large-actor -a demo &# Kill atelet mid-upload
kubectl exec -n ate-system <atelet-pod> -- kill -9 1
# Check /tmp
kubectl exec -n ate-system <atelet-pod> -- ls -lh /tmp/substrate-upload-compress-*# Files remain, potentially several GB each
Call sweepCompressTempFiles() in main.go before the gRPC server starts.
Alternatively, create temp files inside BasePath (the atelet's dedicated volume)
rather than os.TempDir(), so they are isolated from system /tmp and can be swept
by the existing per-actor cleanup paths.
changed the title [-]Compress temp files in os.TempDir() not cleaned on atelet crash — /tmp fills up[/-][+][P3] Compress temp files in os.TempDir() not cleaned on atelet crash — /tmp fills up[/+]on Jul 30, 2026
My plan is to introduce a generic internal/startupsweep package that lets any package register cleanup tasks to be executed on startup.
Both ategcs and imagecache (which has a similar problem with .tmp-* and .rm-* dirs left behind on crash) would register their entries, and main.go would run a single sweeper.Sweep(ctx) call before the gRPC server starts.
Activity
[-]Compress temp files in os.TempDir() not cleaned on atelet crash — /tmp fills up[/-][+][P3] Compress temp files in os.TempDir() not cleaned on atelet crash — /tmp fills up[/+]lorenzo85 commentedon Aug 1, 2026
Hi, I'd like to work on this.
My plan is to introduce a generic
internal/startupsweeppackage that lets any package register cleanup tasks to be executed on startup.Both
ategcsandimagecache(which has a similar problem with.tmp-*and.rm-*dirs left behind on crash) would register their entries, andmain.gowould run a singlesweeper.Sweep(ctx)call before the gRPC server starts.I've put together a fix — draft PR here: #685
atelet: sweep crash-leftover temp files at startup
atelet: sweep crash-leftover temp files at startup