Stop the streamer without sending on closed queues (closes #34)
check / check (push) Successful in 2m40s
check / check (push) Successful in 2m40s
Stop cancels the stream and closes the handler queues under the streamer's write lock, but the read loop only checked for a stop before parsing each line. A stop landing after that check made the loop send the message to a closed queue and panic. The loop now checks again under the read lock it already takes before handing the message to the queues, and returns if the stream was stopped. Stop also clears its cancel function and returns early when there is none, so a second call no longer closes the queues again, as its comment already promised. The new test calls Stop from the raw handler, which runs in exactly that gap, and then calls Stop a second time. Model: opus-5-5
This commit is contained in:
@@ -210,9 +210,14 @@ func (s *Streamer) Start() error {
|
||||
// the connection status in metrics. This method is safe to call multiple times.
|
||||
func (s *Streamer) Stop() {
|
||||
s.mu.Lock()
|
||||
if s.cancel != nil {
|
||||
s.cancel()
|
||||
if s.cancel == nil {
|
||||
// Not started, or already stopped: closing the queues again would panic.
|
||||
s.mu.Unlock()
|
||||
|
||||
return
|
||||
}
|
||||
s.cancel()
|
||||
s.cancel = nil
|
||||
// Close all handler queues to signal workers to stop
|
||||
for _, info := range s.handlers {
|
||||
close(info.queue)
|
||||
@@ -660,8 +665,15 @@ func (s *Streamer) stream(ctx context.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
// Dispatch to interested handlers
|
||||
// Dispatch to interested handlers. Stop cancels ctx and closes the
|
||||
// queues under the write lock, so if ctx is cancelled here, under the
|
||||
// read lock, the queues are closed and must not be sent to.
|
||||
s.mu.RLock()
|
||||
if ctx.Err() != nil {
|
||||
s.mu.RUnlock()
|
||||
|
||||
return ctx.Err()
|
||||
}
|
||||
for _, info := range s.handlers {
|
||||
if !info.handler.WantsMessage(msg.Type) {
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user