From 4a4b17aee3b19741bc021f0d267b8b58d8dc10a5 Mon Sep 17 00:00:00 2001 From: Carl Montanari Date: Tue, 2 Apr 2024 05:06:31 -0700 Subject: [PATCH] fix: handle exiting channel read loop more nicely --- channel/channel.go | 2 ++ channel/read.go | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/channel/channel.go b/channel/channel.go index 4563890..a1ea051 100644 --- a/channel/channel.go +++ b/channel/channel.go @@ -181,6 +181,8 @@ func (c *Channel) Open() (reterr error) { func (c *Channel) Close() error { c.l.Info("channel closing...") + close(c.Errs) + ch := make(chan struct{}) go func() { diff --git a/channel/read.go b/channel/read.go index 3e81843..d18b5bb 100644 --- a/channel/read.go +++ b/channel/read.go @@ -50,6 +50,22 @@ func (c *Channel) read() { b, err := c.t.Read() if err != nil { + select { + case <-c.done: + // this prevents us from ever writing to, what would in this case be, a closed + // errs channel. also if we are "done" we probably only got an error about transport + // dying so we can safely ignore that + return + default: + } + + if errors.Is(err, io.EOF) { + // the underlying transport was closed so just return, we *probably* will have + // already bailed out by reading from the (maybe/probably) closed done channel, but + // if we hit EOF we know we are done anyway + return + } + // we got a transport error, put it into the error channel for processing during // the next read activity, log it, sleep and then try again... c.l.Criticalf( @@ -58,11 +74,6 @@ func (c *Channel) read() { c.Errs <- err - if errors.Is(err, io.EOF) { - // the underlying transport was closed so just return - return - } - time.Sleep(c.ReadDelay) continue