Retry on temporary net.Listener failure
Instead of stopping to listen, retry on temporary failure. This can happen when running out of FDs.
This commit is contained in:
parent
759013750f
commit
859c993a82
29
server.go
29
server.go
|
@ -220,6 +220,8 @@ func (ln *Listener) Start() error {
|
||||||
}
|
}
|
||||||
log.Printf("listening on %q", ln.Address)
|
log.Printf("listening on %q", ln.Address)
|
||||||
|
|
||||||
|
ln.netLn = &retryListener{Listener: ln.netLn}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := ln.serve(); err != nil {
|
if err := ln.serve(); err != nil {
|
||||||
log.Fatalf("listener %q: %v", ln.Address, err)
|
log.Fatalf("listener %q: %v", ln.Address, err)
|
||||||
|
@ -444,3 +446,30 @@ func sslTLV(state *tls.ConnectionState) (proxyproto.TLV, error) {
|
||||||
|
|
||||||
return pp2ssl.Marshal()
|
return pp2ssl.Marshal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type retryListener struct {
|
||||||
|
net.Listener
|
||||||
|
|
||||||
|
delay time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ln *retryListener) Accept() (net.Conn, error) {
|
||||||
|
for {
|
||||||
|
conn, err := ln.Listener.Accept()
|
||||||
|
if ne, ok := err.(net.Error); ok && ne.Temporary() {
|
||||||
|
if ln.delay == 0 {
|
||||||
|
ln.delay = 5 * time.Millisecond
|
||||||
|
} else {
|
||||||
|
ln.delay *= 2
|
||||||
|
}
|
||||||
|
if max := 1 * time.Second; ln.delay > max {
|
||||||
|
ln.delay = max
|
||||||
|
}
|
||||||
|
log.Printf("listener %q: accept error (retrying in %v): %v", ln.Addr(), ln.delay, err)
|
||||||
|
time.Sleep(ln.delay)
|
||||||
|
} else {
|
||||||
|
ln.delay = 0
|
||||||
|
return conn, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue