/** Exit code reserved for the external runner watchdog's runtime deadline. */ export const DAYTONA_RUNTIME_WATCHDOG_EXIT_CODE = 124; /** * Build the tiny parent process that owns the hard runtime deadline outside * the customer-code Node event loop. A synchronous infinite loop can block the * runner's own timer, but it cannot block this separate process. */ export function buildDaytonaRuntimeWatchdogSource(): string { return ` const fs = require('node:fs'); const { spawn } = require('node:child_process'); const runnerPath = process.argv[1]; const configPath = process.argv[2]; const runtimeStartedPath = process.argv[3]; const runtimeCompletedPath = process.argv[4]; const limitMs = Math.max(1, Number.parseInt(process.argv[5] || '', 10) || 1); const startupLimitMs = Math.max(1, Number.parseInt(process.argv[6] || '', 10) || 1); const terminalGraceMs = Math.max(1, Number.parseInt(process.argv[7] || '', 10) || 1); const runtimeLimitMarkerPath = process.argv[8] || ''; const terminationDiagnosticPath = process.argv[9] || ''; const runtimeLimitSeconds = Math.max(1, Math.ceil(limitMs / 1_000)); const child = spawn( process.execPath, ['--max-old-space-size=512', runnerPath, configPath], { env: process.env, stdio: 'inherit', }, ); let timedOut = false; let startupTimedOut = false; let terminalFlushTimedOut = false; let settled = false; let forceKillTimer = null; let runtimeTimer = null; let terminalGraceTimer = null; function writeTerminationDiagnostic(reason, details = {}) { if (!terminationDiagnosticPath) return; try { fs.writeFileSync( terminationDiagnosticPath, JSON.stringify({ schemaVersion: 1, reason, runtimeStarted: fs.existsSync(runtimeStartedPath), runtimeCompleted: fs.existsSync(runtimeCompletedPath), ...details, }), { flag: 'wx' }, ); } catch {} } function stopChild(reason, details) { writeTerminationDiagnostic(reason, details); child.kill('SIGTERM'); forceKillTimer = setTimeout(() => child.kill('SIGKILL'), 1_000); } function markRuntimeLimit() { if (!runtimeLimitMarkerPath) return; try { fs.writeFileSync(runtimeLimitMarkerPath, 'runtime_limit'); } catch {} } function armRuntimeDeadline() { if (settled || runtimeTimer) return; clearTimeout(startupTimer); runtimeTimer = setTimeout(() => { // Close the polling race at the exact deadline: customer code may have // written the completion fence after the last 25ms poll. if (fs.existsSync(runtimeCompletedPath)) { armTerminalGrace(); return; } timedOut = true; markRuntimeLimit(); process.stderr.write( 'RUNTIME_LIMIT_EXCEEDED: Play exceeded its configured ' + runtimeLimitSeconds + ' second runtime limit and was stopped by the external watchdog.\\n', ); stopChild('runtime_limit'); }, limitMs); } function armTerminalGrace() { if (settled || terminalGraceTimer) return; clearInterval(runtimeBoundaryPoll); clearTimeout(startupTimer); if (runtimeTimer) { clearTimeout(runtimeTimer); runtimeTimer = null; } terminalGraceTimer = setTimeout(() => { terminalFlushTimedOut = true; process.stderr.write('RUNTIME_TERMINAL_FLUSH_LIMIT_EXCEEDED: terminal settlement exceeded its grace period.\\n'); stopChild('terminal_flush_limit'); }, terminalGraceMs); } const runtimeBoundaryPoll = setInterval(() => { if (fs.existsSync(runtimeStartedPath)) armRuntimeDeadline(); if (fs.existsSync(runtimeCompletedPath)) armTerminalGrace(); }, 25); const startupTimer = setTimeout(() => { // The startup marker can land between the last poll and this callback. if (fs.existsSync(runtimeStartedPath)) { armRuntimeDeadline(); return; } startupTimedOut = true; clearInterval(runtimeBoundaryPoll); process.stderr.write('RUNTIME_STARTUP_LIMIT_EXCEEDED: runner never reached the customer-code boundary.\\n'); stopChild('startup_limit'); }, startupLimitMs); if (fs.existsSync(runtimeStartedPath)) armRuntimeDeadline(); if (fs.existsSync(runtimeCompletedPath)) armTerminalGrace(); function finish(code) { if (settled) return; settled = true; clearInterval(runtimeBoundaryPoll); clearTimeout(startupTimer); if (runtimeTimer) clearTimeout(runtimeTimer); if (terminalGraceTimer) clearTimeout(terminalGraceTimer); if (forceKillTimer) clearTimeout(forceKillTimer); process.exitCode = timedOut ? ${DAYTONA_RUNTIME_WATCHDOG_EXIT_CODE} : startupTimedOut ? 1 : terminalFlushTimedOut ? 1 : typeof code === 'number' ? code : 1; } child.once('error', (error) => { writeTerminationDiagnostic('child_spawn_error', { errorName: error && typeof error.name === 'string' ? error.name : 'Error', errorCode: error && typeof error.code === 'string' ? error.code : null, }); finish(1); }); child.once('exit', (code, signal) => { writeTerminationDiagnostic('child_exit', { childExitCode: typeof code === 'number' ? code : null, childSignal: typeof signal === 'string' ? signal : null, }); finish(code); }); process.once('SIGTERM', () => stopChild('watchdog_signal', { watchdogSignal: 'SIGTERM' }), ); process.once('SIGINT', () => stopChild('watchdog_signal', { watchdogSignal: 'SIGINT' }), ); `; }