MCPcopy Create free account
hub / github.com/MiniCodeMonkey/chief / runWatchdog

Method runWatchdog

internal/loop/loop.go:402–451  ·  view source on GitHub ↗

runWatchdog monitors lastOutputTime and kills the process if no output is received within the timeout duration. It stops when watchdogDone is closed.

(timeout time.Duration, done <-chan struct{}, fired *atomic.Bool)

Source from the content-addressed store, hash-verified

400// runWatchdog monitors lastOutputTime and kills the process if no output is received
401// within the timeout duration. It stops when watchdogDone is closed.
402func (l *Loop) runWatchdog(timeout time.Duration, done <-chan struct{}, fired *atomic.Bool) {
403 // Check interval scales with timeout: 1/5 of timeout, clamped to [10ms, 10s]
404 checkInterval := timeout / 5
405 if checkInterval < 10*time.Millisecond {
406 checkInterval = 10 * time.Millisecond
407 }
408 if checkInterval > 10*time.Second {
409 checkInterval = 10 * time.Second
410 }
411 ticker := time.NewTicker(checkInterval)
412 defer ticker.Stop()
413
414 for {
415 select {
416 case <-ticker.C:
417 l.mu.Lock()
418 lastOutput := l.lastOutputTime
419 stopped := l.stopped
420 l.mu.Unlock()
421
422 if stopped {
423 return
424 }
425
426 if time.Since(lastOutput) > timeout {
427 fired.Store(true)
428
429 // Emit watchdog timeout event
430 l.mu.Lock()
431 iter := l.iteration
432 l.mu.Unlock()
433 l.events <- Event{
434 Type: EventWatchdogTimeout,
435 Iteration: iter,
436 Text: fmt.Sprintf("No output for %s, killing hung process", timeout),
437 }
438
439 // Kill the process
440 l.mu.Lock()
441 if l.agentCmd != nil && l.agentCmd.Process != nil {
442 l.agentCmd.Process.Kill()
443 }
444 l.mu.Unlock()
445 return
446 }
447 case <-done:
448 return
449 }
450 }
451}
452
453// processOutput reads stdout line by line, logs it, and parses events.
454func (l *Loop) processOutput(r io.Reader) {

Calls 1

StopMethod · 0.45