Series 9 — Part 4 of 5
Audio pipeline processing creates temporary files — WAV from TTS, OGG from conversion. If those temp files are not cleaned up on every code path (including error paths), /tmp fills up silently and the next TTS call fails for a completely unrelated reason. This article covers the correct temp file lifecycle pattern.
The Create-Use-Unlink Pattern
// WRONG: cleanup only on success
$tmpFile = tempnam(sys_get_temp_dir(), 'tts_') . '.wav';
file_put_contents($tmpFile, $wavBytes);
$oggBytes = convert($tmpFile);
unlink($tmpFile); // Only reached if convert() doesn't throw
// CORRECT: cleanup in finally — always runs
$tmpFile = null;
try {
$tmpFile = sys_get_temp_dir() . '/' . bin2hex(random_bytes(8)) . '.wav';
file_put_contents($tmpFile, $wavBytes);
$oggBytes = convert($tmpFile);
} finally {
if ($tmpFile !== null && file_exists($tmpFile)) {
unlink($tmpFile);
}
}
Naming Temp Files Safely
// WRONG: time() is predictable — path traversal risk
$tmp = sys_get_temp_dir() . '/audio_' . time() . '.wav';
// WRONG: uniqid() uses microtime — predictable with system access
$tmp = tempnam(sys_get_temp_dir(), 'tts_'); // Extension not set — harder to type-check
// CORRECT: random_bytes gives cryptographically unpredictable names
function make_temp(string $extension): string
{
return sys_get_temp_dir() . '/' . bin2hex(random_bytes(8)) . '.' . ltrim($extension, '.');
}
$tmpWav = make_temp('wav'); // e.g. /tmp/a3f8b2c7d1e04f9a.wav
PHP register_shutdown_function for Emergency Cleanup
// Register at request start — fires even on fatal errors
$tempFiles = [];
register_shutdown_function(function () use (&$tempFiles) {
foreach ($tempFiles as $path) {
if (file_exists($path)) {
unlink($path);
}
}
});
// Track all temp files
function create_temp(string $ext, array &$registry): string
{
$path = make_temp($ext);
$registry[] = $path;
return $path;
}
$tmpWav = create_temp('wav', $tempFiles);
$tmpOgg = create_temp('ogg', $tempFiles);
// Both will be cleaned up at shutdown regardless of what happens
Monitoring /tmp Growth
# Check /tmp usage
du -sh /tmp
# Find orphaned audio files (older than 10 minutes)
find /tmp -name '*.wav' -o -name '*.ogg' -mmin +10 | wc -l
# Add to cron: clean up any orphaned audio files older than 30 minutes
0 * * * * find /tmp -name '*.wav' -o -name '*.ogg' -mmin +30 -delete
What to Watch For
- Multiple temp files in one pipeline — The WAV → OGG conversion creates two temp files. Track both in the registry from the start, even though the OGG file doesn't exist yet when you register. The shutdown function checks
file_exists()before unlinking. - /tmp as a tmpfs partition — On Raspberry Pi OS, /tmp may be a tmpfs (RAM-backed). Files there don't survive reboots, but they do consume RAM. Monitor /tmp usage on memory-constrained systems.