diff --git a/server_test.go b/server_test.go index 15007389..c7ae3737 100644 --- a/server_test.go +++ b/server_test.go @@ -39,9 +39,15 @@ func AnotherHelloServer(w ResponseWriter, req *Msg) { } func RunLocalUDPServer(laddr string) (*Server, string, error) { + server, l, _, err := RunLocalUDPServerWithFinChan(laddr) + + return server, l, err +} + +func RunLocalUDPServerWithFinChan(laddr string) (*Server, string, chan struct{}, error) { pc, err := net.ListenPacket("udp", laddr) if err != nil { - return nil, "", err + return nil, "", nil, err } server := &Server{PacketConn: pc, ReadTimeout: time.Hour, WriteTimeout: time.Hour} @@ -49,13 +55,16 @@ func RunLocalUDPServer(laddr string) (*Server, string, error) { waitLock.Lock() server.NotifyStartedFunc = waitLock.Unlock + fin := make(chan struct{}, 0) + go func() { server.ActivateAndServe() + close(fin) pc.Close() }() waitLock.Lock() - return server, pc.LocalAddr().String(), nil + return server, pc.LocalAddr().String(), fin, nil } func RunLocalUDPServerUnsafe(laddr string) (*Server, string, error) { @@ -448,7 +457,7 @@ func TestHandlerCloseTCP(t *testing.T) { } func TestShutdownUDP(t *testing.T) { - s, _, err := RunLocalUDPServer("127.0.0.1:0") + s, _, fin, err := RunLocalUDPServerWithFinChan("127.0.0.1:0") if err != nil { t.Fatalf("unable to run test server: %v", err) } @@ -456,6 +465,11 @@ func TestShutdownUDP(t *testing.T) { if err != nil { t.Errorf("could not shutdown test UDP server, %v", err) } + select { + case <-fin: + case <-time.After(2 * time.Second): + t.Error("Could not shutdown test UDP server. Gave up waiting") + } } type ExampleFrameLengthWriter struct { diff --git a/udp_linux.go b/udp_linux.go index 7a107857..c62d2188 100644 --- a/udp_linux.go +++ b/udp_linux.go @@ -24,6 +24,12 @@ func setUDPSocketOptions4(conn *net.UDPConn) error { if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil { 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 { + return err + } return nil } @@ -36,6 +42,10 @@ func setUDPSocketOptions6(conn *net.UDPConn) error { if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil { return err } + err = syscall.SetNonblock(int(file.Fd()), true) + if err != nil { + return err + } return nil }