@@ -295,10 +295,10 @@ func (pool *ConnPool[C]) Close() {
295295// pool closing operation
296296func (pool * ConnPool [C ]) CloseWithContext (ctx context.Context ) error {
297297 pool .capacityMu .Lock ()
298- defer pool .capacityMu .Unlock ()
299298
300- if pool .close .Load () == nil || pool . capacity . Load () == 0 {
299+ if pool .close .Load () == nil {
301300 // already closed
301+ pool .capacityMu .Unlock ()
302302 return nil
303303 }
304304
@@ -310,6 +310,7 @@ func (pool *ConnPool[C]) CloseWithContext(ctx context.Context) error {
310310 closeChan := * pool .close .Swap (nil )
311311 close (closeChan )
312312
313+ pool .capacityMu .Unlock ()
313314 pool .workers .Wait ()
314315 return err
315316}
@@ -318,6 +319,10 @@ func (pool *ConnPool[C]) reopen() {
318319 pool .capacityMu .Lock ()
319320 defer pool .capacityMu .Unlock ()
320321
322+ if pool .close .Load () == nil {
323+ return
324+ }
325+
321326 capacity := pool .capacity .Load ()
322327 if capacity == 0 {
323328 return
@@ -411,6 +416,9 @@ func (pool *ConnPool[C]) Get(ctx context.Context, setting *Setting) (*Pooled[C],
411416 if ctx .Err () != nil {
412417 return nil , ErrCtxTimeout
413418 }
419+ if pool .close .Load () == nil {
420+ return nil , ErrConnPoolClosed
421+ }
414422 if pool .capacity .Load () == 0 {
415423 return nil , ErrConnPoolClosed
416424 }
@@ -427,6 +435,10 @@ func (pool *ConnPool[C]) put(conn *Pooled[C]) {
427435
428436 if conn == nil {
429437 var err error
438+ if pool .close .Load () == nil {
439+ pool .closedConn ()
440+ return
441+ }
430442 // Using context.Background() is fine since MySQL connection already enforces
431443 // a connect timeout via the `db-connect-timeout-ms` config param.
432444 conn , err = pool .connNew (context .Background ())
@@ -453,6 +465,12 @@ func (pool *ConnPool[C]) put(conn *Pooled[C]) {
453465}
454466
455467func (pool * ConnPool [C ]) tryReturnConn (conn * Pooled [C ], updateIdleTime bool ) bool {
468+ if pool .close .Load () == nil {
469+ conn .Close ()
470+ pool .closedConn ()
471+ return false
472+ }
473+
456474 if pool .wait .tryReturnConn (conn ) {
457475 return true
458476 }
@@ -588,6 +606,10 @@ func (pool *ConnPool[C]) closedConn() {
588606
589607func (pool * ConnPool [C ]) getNew (ctx context.Context ) (* Pooled [C ], error ) {
590608 for {
609+ if pool .close .Load () == nil {
610+ return nil , ErrConnPoolClosed
611+ }
612+
591613 open := pool .active .Load ()
592614 if open >= pool .capacity .Load () {
593615 return nil , nil
@@ -599,6 +621,11 @@ func (pool *ConnPool[C]) getNew(ctx context.Context) (*Pooled[C], error) {
599621 pool .closedConn ()
600622 return nil , err
601623 }
624+ if pool .close .Load () == nil {
625+ conn .Close ()
626+ pool .closedConn ()
627+ return nil , ErrConnPoolClosed
628+ }
602629 return conn , nil
603630 }
604631 }
@@ -763,7 +790,12 @@ func (pool *ConnPool[C]) setCapacity(ctx context.Context, newcap int64) error {
763790 }
764791
765792 oldcap := pool .capacity .Swap (newcap )
766- if oldcap == newcap {
793+ // Skip the drain only when capacity is unchanged AND we're already at or
794+ // below the target. Otherwise we may have been left with active > newcap
795+ // by a prior call that timed out (e.g. SetCapacity(0) racing with held
796+ // conns), and CloseWithContext relies on a follow-up call here to finish
797+ // draining.
798+ if oldcap == newcap && pool .active .Load () <= newcap {
767799 return nil
768800 }
769801 // update the idle count to match the new capacity if necessary
0 commit comments