From 4d71620cb08816e17752a71bd59d544a9514cd29 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Sat, 31 Oct 2015 13:22:23 -0600 Subject: [PATCH] core (Windows): Retry every 100ms for 2s if listener fails to bind In testing, I've found that Windows doesn't release the socket right away even though the listener is closed, so calling caddy.Start() right after caddy.Stop() can fail. This change has server.ListenAndServe() try up to 20 times every 100ms to bind the listener, and only return an error if it doesn't succeed after 2 seconds. This might be kind of nifty for Unix, too, but there hasn't been a need for it yet. --- server/server.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/server/server.go b/server/server.go index a1ab6c58..15128996 100644 --- a/server/server.go +++ b/server/server.go @@ -117,8 +117,21 @@ func (s *Server) ListenAndServe() error { ln, err := net.Listen("tcp", s.Addr) if err != nil { - close(s.startChan) - return err + var succeeded bool + if runtime.GOOS == "windows" { // TODO: Limit this to Windows only? (it keeps sockets open after closing listeners) + for i := 0; i < 20; i++ { + time.Sleep(100 * time.Millisecond) + ln, err = net.Listen("tcp", s.Addr) + if err == nil { + succeeded = true + break + } + } + } + if !succeeded { + close(s.startChan) + return err + } } return s.serve(ln.(*net.TCPListener))