diff --git a/main.go b/main.go index 47c7cab0..c18b35e6 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "bufio" "flag" + "context" "net/http" "os" "time" @@ -37,19 +38,24 @@ func RunServer(conf *config.Config) { } l, err := network.CreateHTTPListener(conf) log.CheckError(err) - if err == nil { - // add http server to be closed gracefully - signals.RegisterCloser(&network.GracefulHttpCloser{ - Server: srv, - Listener: l, - }) - log.Infof("listening on %s", l.Addr()) - err := srv.Serve(l) - if err != nil && err != network.ErrListenerStopped { - log.CheckError(err) - } - + if err != nil { + return } + log.Infof("listening on %s", l.Addr()) + // http.Server.Shutdown closes associated listeners/clients. + // context.Background causes srv to indefinitely try to + // gracefully shutdown. add a timeout if this becomes a problem. + signals.OnInterrupt(func() { + srv.Shutdown(context.Background()) + }) + err = srv.Serve(l) + if err == nil { + log.Panic("http.Server.Serve never returns nil") + } + if err == http.ErrServerClosed { + return + } + log.CheckError(err) } // RunScraper runs tracker scraper mainloop @@ -73,10 +79,10 @@ func RunScraper(conf *config.Config) { workers = 1 } - // register udp socket with signals - signals.RegisterCloser(pc) - // register scraper with signals - signals.RegisterCloser(scraper) + signals.OnInterrupt(func() { + pc.Close() + scraper.Close() + }) // run udp scraper worker for workers > 0 { log.Infof("starting up worker %d", workers) @@ -96,7 +102,9 @@ func RunMetainfoFetcher(conf *config.Config) { return } - signals.RegisterCloser(fetcher) + signals.OnInterrupt(func() { + fetcher.Close() + }) fetcher.RunAsync() fetcher.Wait() } diff --git a/network/closer.go b/network/closer.go deleted file mode 100644 index 242726d2..00000000 --- a/network/closer.go +++ /dev/null @@ -1,18 +0,0 @@ -package network - -import ( - "net" - "net/http" -) - -// GracefulHttpCloser : implements io.Closer that gracefully closes an http server -type GracefulHttpCloser struct { - Server *http.Server - Listener net.Listener -} - -// Close method -func (c *GracefulHttpCloser) Close() error { - c.Listener.Close() - return c.Server.Shutdown(nil) -} diff --git a/util/signals/closers.go b/util/signals/closers.go deleted file mode 100644 index 5a4685a3..00000000 --- a/util/signals/closers.go +++ /dev/null @@ -1,26 +0,0 @@ -package signals - -import ( - "io" - "sync" -) - -var ( - closeAccess sync.Mutex - closers []io.Closer -) - -// RegisterCloser adds an io.Closer to close on interrupt -func RegisterCloser(c io.Closer) { - closeAccess.Lock() - closers = append(closers, c) - closeAccess.Unlock() -} - -func closeClosers() { - closeAccess.Lock() - for _, c := range closers { - c.Close() - } - closeAccess.Unlock() -} diff --git a/util/signals/interrupt.go b/util/signals/interrupt.go index 1704b736..6c0792ea 100644 --- a/util/signals/interrupt.go +++ b/util/signals/interrupt.go @@ -3,8 +3,22 @@ package signals import ( "github.com/NyaaPantsu/nyaa/router" "github.com/NyaaPantsu/nyaa/util/log" + "sync" ) +// registered interrupt callbacks. +// currently only used to gracefully close the server. +var intEvents struct { + lock sync.Mutex + funcs []func() +} + +func OnInterrupt(fn func()) { + intEvents.lock.Lock() + intEvents.funcs = append(intEvents.funcs, fn) + intEvents.lock.Unlock() +} + func handleReload() { log.Info("Got SIGHUP") router.ReloadTemplates() @@ -13,5 +27,9 @@ func handleReload() { // handle interrupt signal, platform independent func interrupted() { - closeClosers() + intEvents.lock.Lock() + for _, fn := range intEvents.funcs { + fn() + } + intEvents.lock.Unlock() }