diff --git a/server_test.go b/server_test.go index 1b5cbc97..098be2eb 100644 --- a/server_test.go +++ b/server_test.go @@ -677,3 +677,43 @@ zDCJkckCgYEAndqM5KXGk5xYo+MAA1paZcbTUXwaWwjLU+XSRSSoyBEi5xMtfvUb kFsxKCqxAnBVGEWAvVZAiiTOxleQFjz5RnL0BQp9Lg2cQe+dvuUmIAA= -----END RSA PRIVATE KEY-----`) ) + +func testShutdownBindPort(t *testing.T, protocol string, port string) { + handler := NewServeMux() + handler.HandleFunc(".", func(w ResponseWriter, r *Msg) {}) + startedCh := make(chan struct{}) + s := &Server{ + Addr: net.JoinHostPort("127.0.0.1", port), + Net: protocol, + Handler: handler, + NotifyStartedFunc: func() { + startedCh <- struct{}{} + }, + } + go func() { + if err := s.ListenAndServe(); err != nil { + t.Log(err) + } + }() + <-startedCh + t.Logf("DNS server is started on: %s", s.Addr) + if err := s.Shutdown(); err != nil { + t.Fatal(err) + } + time.Sleep(100 * time.Millisecond) + go func() { + if err := s.ListenAndServe(); err != nil { + t.Fatal(err) + } + }() + <-startedCh + t.Logf("DNS server is started on: %s", s.Addr) +} + +func TestShutdownBindPortUDP(t *testing.T) { + testShutdownBindPort(t, "udp", "1153") +} + +func TestShutdownBindPortTCP(t *testing.T) { + testShutdownBindPort(t, "tcp", "1154") +} diff --git a/udp_linux.go b/udp_linux.go index c62d2188..142a8007 100644 --- a/udp_linux.go +++ b/udp_linux.go @@ -22,14 +22,17 @@ func setUDPSocketOptions4(conn *net.UDPConn) error { return err } if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil { + file.Close() return err } // Calling File() above results in the connection becoming blocking, we must fix that. // See https://github.com/miekg/dns/issues/279 err = syscall.SetNonblock(int(file.Fd()), true) if err != nil { + file.Close() return err } + file.Close() return nil } @@ -40,12 +43,15 @@ func setUDPSocketOptions6(conn *net.UDPConn) error { return err } if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil { + file.Close() return err } err = syscall.SetNonblock(int(file.Fd()), true) if err != nil { + file.Close() return err } + file.Close() return nil } @@ -59,8 +65,10 @@ func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { // dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY) if err != nil { + file.Close() return false, err } + file.Close() return v6only == 1, nil } @@ -69,5 +77,6 @@ func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) { if err != nil { return nil, err } + defer file.Close() return syscall.Getsockname(int(file.Fd())) }