Last active
June 13, 2019 18:25
-
-
Save marcofranssen/699c1aa97c8a33ab20b5eccada275b08 to your computer and use it in GitHub Desktop.
Code not executing line 29 until interrupt channel is received
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
) | |
var ( | |
listenAddr string | |
) | |
func main() { | |
flag.StringVar(&listenAddr, "listen-addr", ":5000", "server listen address") | |
flag.Parse() | |
server, err := NewServer(listenAddr) | |
if err != nil { | |
panic(err) | |
} | |
server.Start() | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"log" | |
"net/http" | |
"os" | |
"os/signal" | |
"time" | |
) | |
// Server provides an http.Server | |
type Server struct { | |
log *log.Logger | |
*http.Server | |
} | |
// NewServer creates and configures an APIServer serving all application routes. | |
func NewServer(listenAddr string) (*Server, error) { | |
logger := log.New(os.Stdout, "http: ", log.LstdFlags) | |
api := http.NewServeMux() | |
if err != nil { | |
return nil, err | |
} | |
srv := http.Server{ | |
Addr: listenAddr, | |
Handler: api, | |
ErrorLog: logger, | |
ReadTimeout: 5 * time.Second, | |
WriteTimeout: 10 * time.Second, | |
IdleTimeout: 15 * time.Second, | |
} | |
return &Server{logger, &srv}, nil | |
} | |
// Start runs ListenAndServe on the http.Server with graceful shutdown | |
func (srv *Server) Start() { | |
srv.log.Println("Starting server...") | |
done := make(chan bool, 1) | |
go srv.gracefullShutdown(done) | |
srv.log.Println("Gracefull shutdown interupt signal registered") | |
// code below will not run until interupt signal is given using ctrl+c | |
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { | |
srv.log.Fatalf("Could not listen on %s: %v\n", srv.Addr, err) | |
} | |
srv.log.Println("Server is ready to handle requests at", srv.Addr) | |
<-done | |
src.log.Println("Server stopped") | |
} | |
func (srv *Server) gracefullShutdown(done chan<- bool) { | |
quit := make(chan os.Signal) | |
signal.Notify(quit, os.Interrupt) | |
sig := <-quit | |
srv.log.Println("Server is shutting down... Reason:", sig) | |
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | |
defer cancel() | |
srv.SetKeepAlivesEnabled(false) | |
if err := srv.Shutdown(ctx); err != nil { | |
srv.log.Fatalf("Could not gracefully shutdown the server: %v\n", err) | |
} | |
close(done) | |
} |
I found the solution with some help of a fellow gopher.
It appears I swapped my logline with the location of that logline in my original implementation.
Before I was logging before the line with ListenAndServer
now I moved it after. ListenAndServe
ofcourse is blocking operation.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The result of running the webserver currently behaves as following.
$ go build && ./my-api.exe http: 2019/06/13 19:51:40 Starting server... http: 2019/06/13 19:51:40 after grace routine http: 2019/06/13 19:51:45 Server is shutting down... Reason: interrupt http: 2019/06/13 19:51:45 Server is ready to handle requests at :5000 http: 2019/06/13 19:51:45 Server stopped
Note the server is only started after the interrupt was received.
I would expect it to behave like this.
$ go build && ./my-api.exe http: 2019/06/13 19:51:40 Starting server... http: 2019/06/13 19:51:40 after grace routine http: 2019/06/13 19:51:40 Server is ready to handle requests at :5000 http: 2019/06/13 19:51:45 Server is shutting down... Reason: interrupt http: 2019/06/13 19:51:45 Server stopped
Note the server starts immediately and five seconds later the interrupt is given and the server is shutdown.
This more simpler less structured example I blogged about earlier works perfectly as expected.
https://marcofranssen.nl/go-webserver-with-gracefull-shutdown/#TLDR
I just don't understand why my new code with a bit more structure doesn't work. Could anyone explain this?