Set UDP conn to non-blocking on Linux to fix Shutdown()
The call to conn.File() causes Go to call dup() and then set the resulting FD to be blocking. This sets the FD back to non-blocking, allowing Shutdown() to work properly. Fixes #279.
This commit is contained in:
parent
f520760857
commit
7b51cba64a
|
@ -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 {
|
||||
|
|
10
udp_linux.go
10
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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue