diff --git a/frontend/udp/frontend.go b/frontend/udp/frontend.go index bc5b421..a75430e 100644 --- a/frontend/udp/frontend.go +++ b/frontend/udp/frontend.go @@ -84,8 +84,13 @@ func NewFrontend(logic frontend.TrackerLogic, cfg Config) (*Frontend, error) { }, } + err := f.listen() + if err != nil { + return nil, err + } + go func() { - if err := f.listenAndServe(); err != nil { + if err := f.serve(); err != nil { log.Fatal("failed while serving udp", log.Err(err)) } }() @@ -112,19 +117,19 @@ func (t *Frontend) Stop() stop.Result { return c.Result() } -// listenAndServe blocks while listening and serving UDP BitTorrent requests -// until Stop() is called or an error is returned. -func (t *Frontend) listenAndServe() error { +// listen resolves the address and binds the server socket. +func (t *Frontend) listen() error { udpAddr, err := net.ResolveUDPAddr("udp", t.Addr) if err != nil { return err } - t.socket, err = net.ListenUDP("udp", udpAddr) - if err != nil { - return err - } + return err +} +// serve blocks while listening and serving UDP BitTorrent requests +// until Stop() is called or an error is returned. +func (t *Frontend) serve() error { pool := bytepool.New(2048) t.wg.Add(1) @@ -134,7 +139,7 @@ func (t *Frontend) listenAndServe() error { // Check to see if we need to shutdown. select { case <-t.closing: - log.Debug("udp listenAndServe() received shutdown signal") + log.Debug("udp serve() received shutdown signal") return nil default: } diff --git a/frontend/udp/frontend_test.go b/frontend/udp/frontend_test.go new file mode 100644 index 0000000..b4cff14 --- /dev/null +++ b/frontend/udp/frontend_test.go @@ -0,0 +1,28 @@ +package udp_test + +import ( + "testing" + + "github.com/chihaya/chihaya/frontend/udp" + "github.com/chihaya/chihaya/middleware" + "github.com/chihaya/chihaya/storage" + _ "github.com/chihaya/chihaya/storage/memory" +) + +func TestStartStopRaceIssue437(t *testing.T) { + ps, err := storage.NewPeerStore("memory", nil) + if err != nil { + t.Fatal(err) + } + var responseConfig middleware.ResponseConfig + lgc := middleware.NewLogic(responseConfig, ps, nil, nil) + fe, err := udp.NewFrontend(lgc, udp.Config{Addr: "127.0.0.1:0"}) + if err != nil { + t.Fatal(err) + } + errC := fe.Stop() + errs := <-errC + if len(errs) != 0 { + t.Fatal(errs[0]) + } +}