David - Musings of an SRE

The Signal Pattern

The signal pattern can be used to ensure your long-lived processes (ie. servers) are able to handle signals being sent to the process.

import ...

type Handler struct {
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  w.Write([]byte(`{}`))
}

func main() {

  h := &Handler{}

  sigCh := make(chan os.Signal, 1)
  errCh := make(chan error, 1)

  signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP)

  go func() {
    err := http.ListenAndServe(":3000", h)
    errCh <- err
  }()

  for {
    select {
    case sig := <-sigCh:
      switch sig {
      case syscall.SIGHUP:
        log.Println("woot woot sighup ", sig)
        os.Exit(0)
      case syscall.SIGTERM:
        log.Println("sigterm ", sig)
        os.Exit(0)
      case syscall.SIGINT:
        log.Println("sig interrupt ", sig)
      }

    case err := <-errCh:
      log.Println(err)
      os.Exit(1)

    }
  }
}

Many thanks to @chuyeow for introducing this pattern to me.

References