{"action":"created","issue":{"url":"https://api.github.com/repos/miekg/dns/issues/279","labels_url":"https://api.github.com/repos/miekg/dns/issues/279/labels{/name}","comments_url":"https://api.github.com/repos/miekg/dns/issues/279/comments","events_url":"https://api.github.com/repos/miekg/dns/issues/279/events","html_url":"https://github.com/miekg/dns/issues/279","id":112792696,"number":279,"title":"Shutdown() not shutting down","user":{"login":"peter-mogensen","id":1792633,"avatar_url":"https://avatars.githubusercontent.com/u/1792633?v=3","gravatar_id":"","url":"https://api.github.com/users/peter-mogensen","html_url":"https://github.com/peter-mogensen","followers_url":"https://api.github.com/users/peter-mogensen/followers","following_url":"https://api.github.com/users/peter-mogensen/following{/other_user}","gists_url":"https://api.github.com/users/peter-mogensen/gists{/gist_id}","starred_url":"https://api.github.com/users/peter-mogensen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peter-mogensen/subscriptions","organizations_url":"https://api.github.com/users/peter-mogensen/orgs","repos_url":"https://api.github.com/users/peter-mogensen/repos","events_url":"https://api.github.com/users/peter-mogensen/events{/privacy}","received_events_url":"https://api.github.com/users/peter-mogensen/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":7,"created_at":"2015-10-22T12:30:49Z","updated_at":"2015-12-01T19:55:35Z","closed_at":null,"body":"I noticed a while ago that shutdown of your DNS server library stopped working in my example code.\r\n\r\nI got around to investigating the reason and I believe the problem was introduced by calling .File() on the listener which in turn causes the Go std lib to call dup(2) on the file descriptor and setting it in non-blocking mode.\r\nThat causes the standard method of stopping Serve() by closing the listener to not work.\r\n\r\nI don't think that issue is covered by the existing server_test.go.\r\n\r\nBelow is a patch against current master server_test.go to illustrate the problem - and a small monkey-patch to udp_linux.go to make the problem go away (it's probably not the most elegant way to solve it)\r\n\r\n```\r\nThe attached example is for UDP, but I believe the problem is the same for TCP. \r\n==================================================================\r\ndiff --git a/server_test.go b/server_test.go\r\nindex b3e0c72..0f26e32 100644\r\n--- a/server_test.go\r\n+++ b/server_test.go\r\n@@ -37,6 +37,29 @@ func AnotherHelloServer(w ResponseWriter, req *Msg) {\r\n \tw.WriteMsg(m)\r\n }\r\n \r\n+func RunLocalUDPServer2(laddr string) (*Server, string, chan struct{}, error) {\r\n+\tpc, err := net.ListenPacket(\"udp\", laddr)\r\n+\tif err != nil {\r\n+\t\treturn nil, \"\", nil, err\r\n+\t}\r\n+\tserver := &Server{PacketConn: pc, ReadTimeout: time.Hour, WriteTimeout: time.Hour}\r\n+\r\n+\twaitLock := sync.Mutex{}\r\n+\twaitLock.Lock()\r\n+\tserver.NotifyStartedFunc = waitLock.Unlock\r\n+\r\n+\tfin := make(chan struct{},0)\r\n+\t\r\n+\tgo func() {\r\n+\t\tserver.ActivateAndServe()\r\n+\t\tclose(fin)\r\n+\t\tpc.Close()\r\n+\t}()\r\n+\r\n+\twaitLock.Lock()\r\n+\treturn server, pc.LocalAddr().String(), fin, nil\r\n+}\r\n+\r\n func RunLocalUDPServer(laddr string) (*Server, string, error) {\r\n \tpc, err := net.ListenPacket(\"udp\", laddr)\r\n \tif err != nil {\r\n@@ -47,7 +70,7 @@ func RunLocalUDPServer(laddr string) (*Server, string, error) {\r\n \twaitLock := sync.Mutex{}\r\n \twaitLock.Lock()\r\n \tserver.NotifyStartedFunc = waitLock.Unlock\r\n-\r\n+\t\r\n \tgo func() {\r\n \t\tserver.ActivateAndServe()\r\n \t\tpc.Close()\r\n@@ -390,7 +413,7 @@ func TestShutdownTCP(t *testing.T) {\r\n }\r\n \r\n func TestShutdownUDP(t *testing.T) {\r\n-\ts, _, err := RunLocalUDPServer(\"127.0.0.1:0\")\r\n+\ts, _, fin, err := RunLocalUDPServer2(\"127.0.0.1:0\")\r\n \tif err != nil {\r\n \t\tt.Fatalf(\"Unable to run test server: %v\", err)\r\n \t}\r\n@@ -398,6 +421,12 @@ func TestShutdownUDP(t *testing.T) {\r\n \tif err != nil {\r\n \t\tt.Errorf(\"Could not shutdown test UDP server, %v\", err)\r\n \t}\r\n+\ttime.Sleep(time.Duration(2)*time.Second) // give it time to shut down.\r\n+\tselect {\r\n+\tcase <-fin:\r\n+\tdefault:\r\n+\t\tt.Error(\"Could not shutdown test UDP server. Gave up waiting\")\r\n+\t}\r\n }\r\n \r\n type ExampleFrameLengthWriter struct {\r\ndiff --git a/udp_linux.go b/udp_linux.go\r\nindex 7a10785..307ef22 100644\r\n--- a/udp_linux.go\r\n+++ b/udp_linux.go\r\n@@ -24,6 +24,10 @@ func setUDPSocketOptions4(conn *net.UDPConn) error {\r\n \tif err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {\r\n \t\treturn err\r\n \t}\r\n+\terr = syscall.SetNonblock(int(file.Fd()), true)\r\n+\tif err != nil {\r\n+\t\treturn err\r\n+\t}\r\n \treturn nil\r\n }\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/miekg/dns/issues/comments/161077589","html_url":"https://github.com/miekg/dns/issues/279#issuecomment-161077589","issue_url":"https://api.github.com/repos/miekg/dns/issues/279","id":161077589,"user":{"login":"miekg","id":353371,"avatar_url":"https://avatars.githubusercontent.com/u/353371?v=3","gravatar_id":"","url":"https://api.github.com/users/miekg","html_url":"https://github.com/miekg","followers_url":"https://api.github.com/users/miekg/followers","following_url":"https://api.github.com/users/miekg/following{/other_user}","gists_url":"https://api.github.com/users/miekg/gists{/gist_id}","starred_url":"https://api.github.com/users/miekg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/miekg/subscriptions","organizations_url":"https://api.github.com/users/miekg/orgs","repos_url":"https://api.github.com/users/miekg/repos","events_url":"https://api.github.com/users/miekg/events{/privacy}","received_events_url":"https://api.github.com/users/miekg/received_events","type":"User","site_admin":false},"created_at":"2015-12-01T19:55:35Z","updated_at":"2015-12-01T19:55:35Z","body":"[ Quoting <notifications@github.com> in \"Re: [dns] Shutdown() not shutting d...\" ]\n>I tried making the same `syscall.SetNonblock()` call on the `*net.UDPConn` in my code, but it did not fix the problem. Adding it to `setUDPSocketOptions4()` in up_linux.go fixes it for me in my project. Maybe this isn't the right fix, but it is better than having the server lockup on Shutdown.\n\nSorry for being super lazy here, but I'm very busy with work atm. Can you send a\nPR for this?\n\nThanks!\n\n/Miek\n\n--\nMiek Gieben\n"}}