fix(backend): only kill processes started by TUI
Track PIDs of backends started by /backend command and only kill those specific PIDs. Previous implementation used pkill which would kill all Ollama/llama-server processes including those started by the user or systemd services. Now we only terminate processes we started.
This commit is contained in:
@@ -52,6 +52,7 @@ export class MinimalTui {
|
||||
private totalUsage: TokenUsage = { inputTokens: 0, outputTokens: 0 };
|
||||
private currentHint = '';
|
||||
private lastLine = '';
|
||||
private backendPids: Map<string, number> = new Map();
|
||||
|
||||
constructor(private config: MinimalTuiConfig) {}
|
||||
|
||||
@@ -322,24 +323,30 @@ export class MinimalTui {
|
||||
}
|
||||
|
||||
private async stopBackend(provider: string): Promise<void> {
|
||||
const pid = this.backendPids.get(provider);
|
||||
if (!pid) {
|
||||
return; // No tracked PID, process not started by us
|
||||
}
|
||||
|
||||
try {
|
||||
const { spawn } = await import('child_process');
|
||||
let processName: string;
|
||||
switch (provider) {
|
||||
case 'ollama':
|
||||
processName = 'ollama';
|
||||
break;
|
||||
case 'llamacpp':
|
||||
processName = 'llama-server';
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
process.kill(pid, 'SIGTERM');
|
||||
// Wait up to 2 seconds for graceful shutdown
|
||||
await new Promise<void>((resolve) => {
|
||||
spawn('pkill', [processName]).on('close', resolve);
|
||||
const timeout = setTimeout(resolve, 2000);
|
||||
const checkInterval = setInterval(() => {
|
||||
try {
|
||||
process.kill(pid, 0); // Check if process exists
|
||||
} catch {
|
||||
clearInterval(checkInterval);
|
||||
clearTimeout(timeout);
|
||||
resolve();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
this.backendPids.delete(provider);
|
||||
} catch (error) {
|
||||
// Ignore errors stopping backends
|
||||
// Process already dead or permission error
|
||||
this.backendPids.delete(provider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,18 +355,25 @@ export class MinimalTui {
|
||||
const { spawn } = await import('child_process');
|
||||
const args: string[] = [];
|
||||
|
||||
let proc: ReturnType<typeof spawn> | undefined;
|
||||
|
||||
switch (provider) {
|
||||
case 'ollama':
|
||||
spawn('ollama', ['serve'], { detached: true, stdio: 'ignore' }).unref();
|
||||
proc = spawn('ollama', ['serve'], { detached: true, stdio: 'ignore' });
|
||||
break;
|
||||
case 'llamacpp':
|
||||
args.push('--model', config.model);
|
||||
args.push('--port', new URL(config.endpoint ?? 'http://localhost:8080').port || '8080');
|
||||
args.push('--host', '0.0.0.0');
|
||||
spawn('llama-server', args, { detached: true, stdio: 'ignore' }).unref();
|
||||
proc = spawn('llama-server', args, { detached: true, stdio: 'ignore' });
|
||||
break;
|
||||
}
|
||||
|
||||
if (proc && proc.pid) {
|
||||
proc.unref();
|
||||
this.backendPids.set(provider, proc.pid);
|
||||
}
|
||||
|
||||
// Wait briefly for the daemon to start
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user