package server import ( "context" "io/ioutil" "os" "os/signal" "runtime" "strconv" "strings" "syscall" "github.com/fnproject/fn/api/common" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" ) func init() { // gin is not nice by default, this can get set in logging initialization gin.SetMode(gin.ReleaseMode) } func getEnv(key, fallback string) string { if value, ok := os.LookupEnv(key); ok { return value } else if value, ok := os.LookupEnv(key + "_FILE"); ok { dat, err := ioutil.ReadFile(value) if err == nil { return string(dat) } } return fallback } func getEnvInt(key string, fallback int) int { if value, ok := os.LookupEnv(key); ok { // linter liked this better than if/else var err error var i int if i, err = strconv.Atoi(value); err != nil { panic(err) // not sure how to handle this } return i } else if value, ok := os.LookupEnv(key + "_FILE"); ok { dat, err := ioutil.ReadFile(value) if err == nil { var err error var i int if i, err = strconv.Atoi(strings.TrimSpace(string(dat))); err != nil { panic(err) // not sure how to handle this } return i } } return fallback } func contextWithSignal(ctx context.Context, signals ...os.Signal) (context.Context, context.CancelFunc) { newCTX, halt := context.WithCancel(ctx) c := make(chan os.Signal, 1) signal.Notify(c, signals...) go func() { for { select { case <-c: common.Logger(ctx).Info("Halting...") halt() return case <-ctx.Done(): common.Logger(ctx).Info("Halting... Original server context canceled.") halt() return } } }() return newCTX, halt } // Installs a child process reaper if init process func installChildReaper() { // assume responsibilities of init process if running as init process for Linux if runtime.GOOS != "linux" || os.Getpid() != 1 { return } var sigs = make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGCHLD) // we run this forever and leak a go routine. As init, we must // reap our children until the very end, so this is OK. go func() { for { <-sigs for { var status syscall.WaitStatus var rusage syscall.Rusage pid, err := syscall.Wait4(-1, &status, syscall.WNOHANG, &rusage) // no children if pid <= 0 { break } logrus.Infof("Child terminated pid=%d err=%v status=%v usage=%v", pid, err, status, rusage) } } }() }