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:
Simon Ser 2022-02-03 10:36:08 +01:00
parent 759013750f
commit 859c993a82
1 changed files with 29 additions and 0 deletions

View File

@ -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
}
}
}