Skip to content

Commit 94bb50b

Browse files
committed
fix: make chanSend non-blocking to prevent panic on closed channel
The RAG file watcher runs for the lifetime of the agent but holds a closure over the per-message events channel. When finalizeEventChannel closes that channel between messages, the watcher panics with "send on closed channel". Make chanSend non-blocking with select/default and recover from panics on closed channels, so late-arriving RAG events are safely dropped. Fixes #2266 Assisted-By: docker-agent
1 parent 2021b77 commit 94bb50b

2 files changed

Lines changed: 13 additions & 3 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ require (
185185
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
186186
github.com/opencontainers/go-digest v1.0.0 // indirect
187187
github.com/opencontainers/image-spec v1.1.1 // indirect
188-
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
188+
github.com/patrickmn/go-cache v2.1.0+incompatible
189189
github.com/perimeterx/marshmallow v1.1.5 // indirect
190190
github.com/pjbgf/sha1cd v0.3.2 // indirect
191191
github.com/pmezard/go-difflib v1.0.0 // indirect

pkg/runtime/loop.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,17 @@ func formatToolWarning(a *agent.Agent, warnings []string) string {
576576
return strings.TrimSuffix(builder.String(), "\n")
577577
}
578578

579-
// chanSend wraps a channel as a func(Event) for use with emitAgentWarnings.
579+
// chanSend wraps a channel as a func(Event) for use with emitAgentWarnings
580+
// and RAG event forwarding. The send is non-blocking: if the channel is full
581+
// or closed, the event is silently dropped. This prevents a panic when a
582+
// long-lived goroutine (e.g. RAG file watcher) tries to forward an event
583+
// after the per-message events channel has been closed.
580584
func chanSend(ch chan Event) func(Event) {
581-
return func(e Event) { ch <- e }
585+
return func(e Event) {
586+
defer func() { recover() }() //nolint:errcheck // swallow send-on-closed-channel panic
587+
select {
588+
case ch <- e:
589+
default:
590+
}
591+
}
582592
}

0 commit comments

Comments
 (0)