66 "crypto/tls"
77 "net"
88 "sync"
9+ "sync/atomic"
910 "time"
1011)
1112
@@ -27,6 +28,16 @@ type Accepter struct {
2728 connsMu sync.RWMutex
2829}
2930
31+ var (
32+ maxTempDelay time.Duration
33+ )
34+
35+ // SetMaxTempDelay sets maximum temporary error wait duration as concurrent-safe.
36+ // Zero or negative values mean to wait forever. By default, zero.
37+ func SetMaxTempDelay (d time.Duration ) {
38+ atomic .StoreInt64 ((* int64 )(& maxTempDelay ), int64 (d ))
39+ }
40+
3041// Shutdown gracefully shuts down the Accepter without interrupting any
3142// connections. Shutdown works by first closing the Accepter's underlying Listener, then
3243// cancels the context on Serve method of Handler, and then waiting indefinitely for
@@ -127,7 +138,7 @@ func (a *Accepter) Serve(lis net.Listener) (err error) {
127138 a .ctx , a .ctxCancel = context .WithCancel (context .Background ())
128139 defer a .ctxCancel ()
129140 a .conns = make (map [net.Conn ]struct {})
130- var tempDelay time.Duration
141+ var tempDelay , totalDelay time.Duration
131142 for {
132143 var conn net.Conn
133144 conn , err = lis .Accept ()
@@ -139,6 +150,10 @@ func (a *Accepter) Serve(lis net.Listener) (err error) {
139150 default :
140151 }
141152 if ne , ok := err .(net.Error ); ok && ne .Temporary () {
153+ maxDelay := time .Duration (atomic .LoadInt64 ((* int64 )(& maxTempDelay )))
154+ if maxDelay > 0 && totalDelay > maxDelay {
155+ return
156+ }
142157 if tempDelay == 0 {
143158 tempDelay = 5 * time .Millisecond
144159 } else {
@@ -148,11 +163,13 @@ func (a *Accepter) Serve(lis net.Listener) (err error) {
148163 tempDelay = max
149164 }
150165 time .Sleep (tempDelay )
166+ totalDelay += tempDelay
151167 continue
152168 }
153169 return
154170 }
155171 tempDelay = 0
172+ totalDelay = 0
156173 go a .serve (conn )
157174 }
158175}
0 commit comments