I'm in the process of getting my HTTP server to gracefully shut down. I've taken tips from the post here, and have set up my code like this so far:
func start() {
//......
//START HTTP/SOCKET LISTENER
if settings.TLS {
httpServer = makeServer("/wss", settings.TLS);
} else {
httpServer = makeServer("/ws", settings.TLS);
}
//...
}
func makeServer(handleDir string, tls bool) (*http.Server) {
server := &http.Server{Addr: settings.IP+":"+strconv.Itoa(settings.Port)}
http.HandleFunc(handleDir, socketInitializer)
if tls {
go func() {
err := server.ListenAndServeTLS(settings.CertFile, settings.PrivKeyFile)
if err != nil {
serverError(err)
}
}()
}else{
go func() {
err := server.ListenAndServe()
if err != nil {
serverError(err)
}
}()
}
//
return server
}
So, I have some questions about how this all works now:
1) The answer I linked above states "NOTE: there is a chance that next line won't have time to run..." for the ListenAndServe()
error handling inside the goroutine. How can I make sure that serverError()
will guarantee completion? Do I need to do some sort of blocking on that thread or do I make a channel on the main thread that it can call?
2) As of right now, I'm not sure if I have a way of telling if I've Server.ShutDown()
the http.Server
, or if it threw an error and shut itself down. Does the ListenAndServe()
error get thrown even if I used the Server.ShutDown()
method? Is that why the accepted answer in the link uses err != http.ErrServerClosed
when checking the ListenAndServe()
error?
3) The start()
function is (of course) ran on the main thread. Don't I need to block that thread somehow so the program doesn't return and exit, or does ListenAndServe()
take care of that for me?
4) After I call Server.ShutDown()
do I need to do anything to shut down the http.HandleFunc()
listeners?
Any amount of help on any of these topics would be greatly appreciated, so don't worry if you can't touch on everything at once :)
EDIT: If anyone wants to see how I ended up getting this all to work right, you can look at this file, line 225 and on.
main
function should somehow wait for all go routines which you want completely done.So, the 1) question: you should block on the main routine to make sure
serverError
can be executed.And the 3) question: absolutely you should block on
start()
or outsidestart()
by yourself, or the program will exit immediately.As for 2). the doc points out:
so
err != http.ErrServerClosed
just works for situationServer.ShutDown()
. Yet there's other errors may occur.4) Nothing to do to shut down the
http.HandleFunc()
becauseServer.ShutDown()
will wait for requests which is processing done.