Skip to main content
Glama
test-termination-edge-cases.js4.58 kB
#!/usr/bin/env node const { ProcessManager } = require('../dist/process-manager.js') const { exec } = require('child_process') const { promisify } = require('util') const execAsync = promisify(exec) const colors = { reset: '\x1b[0m', green: '\x1b[32m', red: '\x1b[31m', yellow: '\x1b[33m', blue: '\x1b[34m', gray: '\x1b[90m' } async function isProcessRunning(pid) { try { process.kill(pid, 0) return true } catch (err) { return false } } async function testEdgeCases() { console.log(`${colors.blue}=== Testing Edge Cases ===${colors.reset}\n`) const config = { processes: { "stubborn": { "command": "node", "args": ["test-stubborn-process.js"], "cwd": __dirname, "startupDelay": 1000 }, "detached-process": { "command": "node", "args": ["-e", "const { spawn } = require('child_process'); console.log('Parent spawning detached child...'); const child = spawn('node', ['-e', 'setInterval(() => console.log(\"Detached child running\"), 1000)'], { detached: true, stdio: 'ignore' }); child.unref(); console.log('Parent exiting, leaving detached child...');"], "startupDelay": 1000 } } } const pm = new ProcessManager(config.processes) // Test 1: Stubborn process that ignores SIGTERM console.log(`${colors.yellow}Test 1: Stubborn process ignoring SIGTERM${colors.reset}`) const result1 = await pm.restart('stubborn') console.log(`Started: ${result1.success}`) await new Promise(resolve => setTimeout(resolve, 2000)) const processes = pm.listProcesses() const stubbornProcess = processes.find(p => p.name === 'stubborn') console.log(`Stubborn process PID: ${stubbornProcess.pid}`) // Get logs before stopping const logsBefore = pm.getLogs('stubborn', 5) console.log('\nLogs before stop:') logsBefore.slice(-3).forEach(log => console.log(` ${colors.gray}${log}${colors.reset}`)) console.log('\nStopping stubborn process (should force kill after 5 seconds)...') const stopStart = Date.now() await pm.stop('stubborn') const stopDuration = Date.now() - stopStart console.log(`Stop took ${stopDuration}ms`) // Check logs after stop const logsAfter = pm.getLogs('stubborn', 10) console.log('\nLogs after stop:') logsAfter.slice(-5).forEach(log => console.log(` ${colors.gray}${log}${colors.reset}`)) await new Promise(resolve => setTimeout(resolve, 1000)) const stillRunning = await isProcessRunning(stubbornProcess.pid) console.log(`Stubborn process still running: ${stillRunning ? colors.red + 'YES' : colors.green + 'NO'}${colors.reset}`) // Test 2: Process that spawns detached children console.log(`\n${colors.yellow}Test 2: Process with detached children${colors.reset}`) const result2 = await pm.restart('detached-process') console.log(`Started: ${result2.success}`) await new Promise(resolve => setTimeout(resolve, 2000)) // Look for any orphaned node processes console.log('\nChecking for orphaned processes...') try { const { stdout } = await execAsync('ps aux | grep "Detached child running" | grep -v grep || true') if (stdout.trim()) { console.log(`${colors.red}Found orphaned processes:${colors.reset}`) console.log(stdout) } else { console.log(`${colors.green}No orphaned processes found${colors.reset}`) } } catch (err) { console.log('Error checking for orphaned processes:', err.message) } // Clean up await pm.stopAll() // Final check for any lingering processes console.log('\nFinal check for lingering processes...') try { const { stdout } = await execAsync('ps aux | grep -E "test-stubborn|Detached child" | grep -v grep || true') if (stdout.trim()) { console.log(`${colors.red}Found lingering processes:${colors.reset}`) console.log(stdout) // Clean them up const pids = stdout.trim().split('\n').map(line => line.trim().split(/\s+/)[1]) for (const pid of pids) { try { process.kill(pid, 'SIGKILL') console.log(`Killed lingering process ${pid}`) } catch (err) { // Process might have already exited } } } else { console.log(`${colors.green}No lingering processes found${colors.reset}`) } } catch (err) { console.log('Error in final check:', err.message) } console.log(`\n${colors.blue}=== Test Complete ===${colors.reset}`) } testEdgeCases().catch(err => { console.error(`${colors.red}Fatal error:${colors.reset}`, err) process.exit(1) })

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/brennancheung/mcp-rewatch'

If you have feedback or need assistance with the MCP directory API, please join our Discord server