rdma: never run operational sinks on callback threads

Rework the publication handoff so a native callback can never
execute a sink: the channel buffer absorbs the common case, and a
full buffer appends to an overflow list that the worker drains
after the channel instead of falling back to inline publication.
Queued records accumulate across successive sessions and failed
authentications consume no session at all, so capacity accounting
cannot bound the backlog; only removing the fallback closes the
stall. Drop the now-unused session-limit accessor.

Move signature verification back outside the admission barrier:
IAM lookups carry no cancellation, so holding the barrier across
verification let one stalled lookup defer RC shutdown
indefinitely. The handlers enforce admission themselves, and a
failure publication checks the drain state before dispatching, so
it cannot land after the sinks close.

Synchronize metrics producers with Close: the manager now marks
itself closed before closing the datapoint channel, and a
producer that still races the closure recovers instead of
panicking on a send over a closed channel.

Exercise real stale tokens in the reservation generation test:
the original token attempts both release and publish after a
newer claim took over.
This commit is contained in:
Jihyeon Gim
2026-09-09 13:16:52 +09:00
parent 55c82f5e4e
commit e9a2a2f98b
6 changed files with 123 additions and 75 deletions
+7 -16
View File
@@ -174,13 +174,12 @@ type SessionInfo struct {
// unblock), waits for every entered call to leave, then tears the
// server down; it is idempotent and safe from any goroutine.
type RCSvc struct {
srv *C.rc_server
closing atomic.Bool
ops atomic.Int64
once sync.Once
ctx context.Context
cancel context.CancelFunc
maxSessions uint32
srv *C.rc_server
closing atomic.Bool
ops atomic.Int64
once sync.Once
ctx context.Context
cancel context.CancelFunc
}
// Context returns the service-lifetime context. Handlers bind
@@ -189,14 +188,6 @@ func (s *RCSvc) Context() context.Context {
return s.ctx
}
// MaxSessions reports the configured global session limit. The
// operational publication pipeline sizes its queue against it:
// each session publishes exactly one terminal record, so a queue
// this deep can never fill.
func (s *RCSvc) MaxSessions() uint32 {
return s.maxSessions
}
// rcLogSink receives every diagnostic line the C server emits.
// It is stateless and process-global on purpose: the sink must be
// valid from init through destroy, independent of any single
@@ -272,7 +263,7 @@ func Init(opts DeviceOpts) (*RCSvc, error) {
}
installLogSink(srv, opts.Debug)
ctx, cancel := context.WithCancel(context.Background())
return &RCSvc{srv: srv, ctx: ctx, cancel: cancel, maxSessions: opts.MaxSessions}, nil
return &RCSvc{srv: srv, ctx: ctx, cancel: cancel}, nil
}
// TryEnter admits a request into the service. It returns false once