From 51f310c1202ebab0a69fcee055fabd1f85e1a8f1 Mon Sep 17 00:00:00 2001 From: uji Date: Sat, 5 Mar 2022 18:14:42 +0900 Subject: [PATCH] internal/jsonrpc2_v2: add sync.Once for "panic: close of closed channel" in idleListener.run When timeout, closing timeout channel in idleListener.run may be called many times. I added sync.Once field to idleListner for preventing it. Fixes golang/go#51435 --- internal/jsonrpc2_v2/serve.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/internal/jsonrpc2_v2/serve.go b/internal/jsonrpc2_v2/serve.go index fb3516635e9..cd8610766ea 100644 --- a/internal/jsonrpc2_v2/serve.go +++ b/internal/jsonrpc2_v2/serve.go @@ -187,12 +187,13 @@ func NewIdleListener(timeout time.Duration, wrap Listener) Listener { } type idleListener struct { - wrapped Listener - timeout time.Duration - newConns chan *idleCloser - closed chan struct{} - wasTimeout chan struct{} - closeOnce sync.Once + wrapped Listener + timeout time.Duration + newConns chan *idleCloser + closed chan struct{} + wasTimeout chan struct{} + closeOnce sync.Once + timeoutOnce sync.Once } type idleCloser struct { @@ -273,7 +274,7 @@ func (l *idleListener) run() { case <-timeout: // we timed out, only happens when there are no active conns // close the underlying listener, and allow the normal closing process to happen - close(l.wasTimeout) + l.timeoutOnce.Do(func() { close(l.wasTimeout) }) l.wrapped.Close() case <-firstClosed: // a conn closed, remove it from the active list