package server import ( "errors" "fmt" "net" "net/http" "os" "os/signal" "sync" "syscall" "time" ) type StoppableListener struct { *net.TCPListener //Wrapped listener stop chan int //Channel used only to indicate listener should shutdown } var quit chan os.Signal func New(l net.Listener) (*StoppableListener, error) { tcpL, ok := l.(*net.TCPListener) if !ok { return nil, errors.New("Cannot wrap listener") } retval := &StoppableListener{} retval.TCPListener = tcpL retval.stop = make(chan int) return retval, nil } var StoppedError = errors.New("Listener stopped") func (sl *StoppableListener) Accept() (net.Conn, error) { for { //Wait up to one second for a new connection sl.SetDeadline(time.Now().Add(time.Second)) newConn, err := sl.TCPListener.Accept() //Check for the channel being closed select { case <-sl.stop: return nil, StoppedError default: //If the channel is still open, continue as normal } if err != nil { netErr, ok := err.(net.Error) //If this is a timeout, then continue to wait for //new connections if ok && netErr.Timeout() && netErr.Temporary() { continue } } return newConn, err } } func (sl *StoppableListener) Stop() { close(sl.stop) } func TerminateServer() { quit <- syscall.SIGTERM } func Start(port string, r http.Handler) { orgLst, err := net.Listen("tcp", ":"+port) if err != nil { panic(err) } sl, err := New(orgLst) if err != nil { panic(err) } server := http.Server{ Handler: r, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } server.SetKeepAlivesEnabled(false) quit = make(chan os.Signal) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) var wg sync.WaitGroup go func(wg sync.WaitGroup) { wg.Add(1) defer wg.Done() server.Serve(sl) }(wg) fmt.Printf("Started at port : " + port + "\n") select { case signal := <-quit: // wait for a few seconds time.Sleep(1000 * time.Millisecond) fmt.Printf("Got signal:%v\n", signal) } fmt.Printf("Stopping listener\n") sl.Stop() fmt.Printf("Waiting on server\n") wg.Wait() }