Переглянути джерело

fix: gRPC handler panics on clean stream close (nil atomic.Value)

The recv goroutine only calls streamErr.CompareAndSwap when an error
occurs. On a clean client close (io.EOF), the loop sets streamErr to
nothing, ackCh is closed, wg.Wait completes, and we fall through to:

  if se := streamErr.Load().(error); se != nil { return se }

But streamErr.Load() returns the zero value of atomic.Value, which is
the untyped nil interface. A type assertion nil.(error) panics with:

  panic: interface conversion: interface is nil, not error

…killing the ingestd process. Logs from the last M11 attempt show this
exactly: many 'alert accepted' lines, then EOF, then the panic, then
exit 2.

Fix: nil-check the Load result before the type assertion, and use the
ok-form to be defensive. atomic.Value should be loaded with a type-safe
assertion regardless.
Luis Rosales 1 місяць тому
батько
коміт
14daaa6a32
1 змінених файлів з 8 додано та 2 видалено
  1. 8 2
      internal/grpcserver/handler.go

+ 8 - 2
internal/grpcserver/handler.go

@@ -177,8 +177,14 @@ func (s *Server) StreamAlerts(stream pbv1.Ingest_StreamAlertsServer) error {
 	}
 
 	// Check if the stream exited due to a goroutine error.
-	if se := streamErr.Load().(error); se != nil {
-		return se
+	// atomic.Value.Load returns nil if nothing was ever stored; the
+	// type assertion nil.(error) panics with "interface conversion:
+	// interface is nil, not error", so we must guard with a nil check
+	// and a type assertion that reports ok.
+	if v := streamErr.Load(); v != nil {
+		if se, ok := v.(error); ok && se != nil {
+			return se
+		}
 	}
 	return nil
 }