avoid close 'nil' panics if any (#18890)

brings a generic implementation that
prints a stack trace for 'nil' channel
closes(), if not safely closes it.
This commit is contained in:
Harshavardhana
2024-01-28 10:04:17 -08:00
committed by GitHub
parent 38de8e6936
commit 1d3bd02089
47 changed files with 150 additions and 104 deletions
+2 -1
View File
@@ -40,6 +40,7 @@ import (
"github.com/gobwas/ws/wsutil"
"github.com/google/uuid"
"github.com/minio/madmin-go/v3"
xioutil "github.com/minio/minio/internal/ioutil"
"github.com/minio/minio/internal/logger"
"github.com/minio/minio/internal/pubsub"
"github.com/tinylib/msgp/msgp"
@@ -449,7 +450,7 @@ func (c *Connection) WaitForConnect(ctx context.Context) error {
defer cancel()
changed := make(chan State, 1)
go func() {
defer close(changed)
defer xioutil.SafeClose(changed)
for {
c.connChange.Wait()
newState := c.State()
+2 -1
View File
@@ -26,6 +26,7 @@ import (
"sync"
"time"
xioutil "github.com/minio/minio/internal/ioutil"
"github.com/minio/mux"
)
@@ -98,7 +99,7 @@ func SetupTestGrid(n int) (*TestGrid, error) {
res.Listeners = append(res.Listeners, listeners[i])
res.Mux = append(res.Mux, m)
}
close(ready)
xioutil.SafeClose(ready)
for _, m := range res.Managers {
for _, remote := range m.Targets() {
if err := m.Connection(remote).WaitForConnect(ctx); err != nil {
+6 -5
View File
@@ -26,6 +26,7 @@ import (
"sync"
"github.com/minio/minio/internal/hash/sha256"
xioutil "github.com/minio/minio/internal/ioutil"
"github.com/minio/minio/internal/logger"
"github.com/tinylib/msgp/msgp"
)
@@ -579,7 +580,7 @@ func (h *StreamTypeHandler[Payload, Req, Resp]) register(m *Manager, handle func
// Don't add extra buffering
inT = make(chan Req)
go func() {
defer close(inT)
defer xioutil.SafeClose(inT)
for {
select {
case <-ctx.Done():
@@ -607,7 +608,7 @@ func (h *StreamTypeHandler[Payload, Req, Resp]) register(m *Manager, handle func
outT := make(chan Resp)
outDone := make(chan struct{})
go func() {
defer close(outDone)
defer xioutil.SafeClose(outDone)
dropOutput := false
for v := range outT {
if dropOutput {
@@ -629,7 +630,7 @@ func (h *StreamTypeHandler[Payload, Req, Resp]) register(m *Manager, handle func
}
}()
rErr := handle(ctx, plT, inT, outT)
close(outT)
xioutil.SafeClose(outT)
<-outDone
return rErr
}, OutCapacity: h.OutCapacity, InCapacity: h.InCapacity, Subroute: strings.Join(subroute, "/"),
@@ -695,7 +696,7 @@ func (h *StreamTypeHandler[Payload, Req, Resp]) Call(ctx context.Context, c Stre
return nil, fmt.Errorf("internal error: stream request channel nil")
}
go func() {
defer close(stream.Requests)
defer xioutil.SafeClose(stream.Requests)
for req := range reqT {
b, err := req.MarshalMsg(GetByteBuffer()[:0])
if err != nil {
@@ -706,7 +707,7 @@ func (h *StreamTypeHandler[Payload, Req, Resp]) Call(ctx context.Context, c Stre
}
}()
} else if stream.Requests != nil {
close(stream.Requests)
xioutil.SafeClose(stream.Requests)
}
return &TypedStream[Req, Resp]{responses: stream, newResp: h.NewResponse, Requests: reqT}, nil
+4 -3
View File
@@ -26,6 +26,7 @@ import (
"sync/atomic"
"time"
xioutil "github.com/minio/minio/internal/ioutil"
"github.com/minio/minio/internal/logger"
"github.com/zeebo/xxh3"
)
@@ -267,7 +268,7 @@ func (m *muxClient) handleOneWayStream(start time.Time, respHandler chan<- Respo
fmt.Println("Mux", m.MuxID, "Request took", time.Since(start).Round(time.Millisecond))
}()
}
defer close(respHandler)
defer xioutil.SafeClose(respHandler)
var pingTimer <-chan time.Time
if m.deadline == 0 || m.deadline > clientPingInterval {
ticker := time.NewTicker(clientPingInterval)
@@ -324,7 +325,7 @@ func (m *muxClient) handleOneWayStream(start time.Time, respHandler chan<- Respo
func (m *muxClient) handleTwowayResponses(responseCh chan Response, responses chan Response) {
defer m.parent.deleteMux(false, m.MuxID)
defer close(responseCh)
defer xioutil.SafeClose(responseCh)
for resp := range responses {
responseCh <- resp
m.send(message{Op: OpUnblockSrvMux, MuxID: m.MuxID})
@@ -534,7 +535,7 @@ func (m *muxClient) closeLocked() {
return
}
if m.respWait != nil {
close(m.respWait)
xioutil.SafeClose(m.respWait)
m.respWait = nil
}
m.closed = true
+9 -11
View File
@@ -26,6 +26,7 @@ import (
"sync/atomic"
"time"
xioutil "github.com/minio/minio/internal/ioutil"
"github.com/minio/minio/internal/logger"
)
@@ -117,7 +118,7 @@ func newMuxStream(ctx context.Context, msg message, c *Connection, handler Strea
m.inbound = make(chan []byte, inboundCap)
handlerIn = make(chan []byte, 1)
go func(inbound <-chan []byte) {
defer close(handlerIn)
defer xioutil.SafeClose(handlerIn)
// Send unblocks when we have delivered the message to the handler.
for in := range inbound {
handlerIn <- in
@@ -146,7 +147,7 @@ func newMuxStream(ctx context.Context, msg message, c *Connection, handler Strea
if debugPrint {
fmt.Println("muxServer: Mux", m.ID, "Returned with", handlerErr)
}
close(send)
xioutil.SafeClose(send)
}()
// handlerErr is guarded by 'send' channel.
handlerErr = handler.Handle(ctx, msg.Payload, handlerIn, send)
@@ -247,7 +248,7 @@ func (m *muxServer) message(msg message) {
logger.LogIf(m.ctx, fmt.Errorf("muxServer: EOF message with payload"))
}
if m.inbound != nil {
close(m.inbound)
xioutil.SafeClose(m.inbound)
m.inbound = nil
}
return
@@ -324,12 +325,9 @@ func (m *muxServer) close() {
m.cancel()
m.recvMu.Lock()
defer m.recvMu.Unlock()
if m.inbound != nil {
close(m.inbound)
m.inbound = nil
}
if m.outBlock != nil {
close(m.outBlock)
m.outBlock = nil
}
xioutil.SafeClose(m.inbound)
m.inbound = nil
xioutil.SafeClose(m.outBlock)
m.outBlock = nil
}