diff --git a/internal/pool/export_test.go b/internal/pool/export_test.go index f3a65f863..40e387c9a 100644 --- a/internal/pool/export_test.go +++ b/internal/pool/export_test.go @@ -12,3 +12,13 @@ func (cn *Conn) SetCreatedAt(tm time.Time) { func (cn *Conn) NetConn() net.Conn { return cn.netConn } + +func (p *ConnPool) CheckMinIdleConns() { + p.connsMu.Lock() + p.checkMinIdleConns() + p.connsMu.Unlock() +} + +func (p *ConnPool) QueueLen() int { + return len(p.queue) +} diff --git a/internal/pool/pool.go b/internal/pool/pool.go index 6d3381c9f..9644cb85b 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -130,6 +130,18 @@ func (p *ConnPool) checkMinIdleConns() { p.idleConnsLen++ go func() { + defer func() { + if err := recover(); err != nil { + p.connsMu.Lock() + p.poolSize-- + p.idleConnsLen-- + p.connsMu.Unlock() + + p.freeTurn() + internal.Logger.Printf(context.Background(), "addIdleConn panic: %+v", err) + } + }() + err := p.addIdleConn() if err != nil && err != ErrClosed { p.connsMu.Lock() diff --git a/internal/pool/pool_test.go b/internal/pool/pool_test.go index 05949e42f..736323d9d 100644 --- a/internal/pool/pool_test.go +++ b/internal/pool/pool_test.go @@ -361,6 +361,24 @@ var _ = Describe("race", func() { Expect(stats.TotalConns).To(Equal(uint32(opt.PoolSize))) }) + It("recover addIdleConn panic", func() { + opt := &pool.Options{ + Dialer: func(ctx context.Context) (net.Conn, error) { + panic("test panic") + }, + PoolSize: 100, + MinIdleConns: 30, + } + p := pool.NewConnPool(opt) + + p.CheckMinIdleConns() + + Eventually(func() bool { + state := p.Stats() + return state.TotalConns == 0 && state.IdleConns == 0 && p.QueueLen() == 0 + }, "3s", "50ms").Should(BeTrue()) + }) + It("wait", func() { opt := &pool.Options{ Dialer: func(ctx context.Context) (net.Conn, error) {