// Handle lifecycle events func handleSignals(srv *falcore.Server) { var sig os.Signal var sigChan = make(chan os.Signal) signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGUSR1, syscall.SIGINT, syscall.SIGTERM, syscall.SIGTSTP) pid := syscall.Getpid() for { sig = <-sigChan switch sig { case syscall.SIGHUP: // send this to the paraent process to initiate the restart fmt.Println(pid, "Received SIGHUP. forking.") cpid, err := forker(srv) fmt.Println(pid, "Forked pid:", cpid, "errno:", err) case syscall.SIGUSR1: // child sends this back to the parent when it's ready to Accept fmt.Println(pid, "Received SIGUSR1. Stopping accept.") srv.StopAccepting() case syscall.SIGINT: fmt.Println(pid, "Received SIGINT. Shutting down.") os.Exit(0) case syscall.SIGTERM: fmt.Println(pid, "Received SIGTERM. Terminating.") os.Exit(0) case syscall.SIGTSTP: fmt.Println(pid, "Received SIGTSTP. Stopping.") syscall.Kill(pid, syscall.SIGSTOP) default: fmt.Println(pid, "Received", sig, ": ignoring") } } }
// setup and fork/exec myself. Make sure to keep open important FD's that won't get re-created by the child // specifically, std* and your listen socket func forker(srv *falcore.Server) (pid int, err error) { var socket string // At version 1.0.3 the socket FD behavior changed and the fork socket is always 3 // 0 = stdin, 1 = stdout, 2 = stderr, 3 = acceptor socket // This is because the ForkExec dups all the saved FDs down to // start at 0. This is also why you MUST include 0,1,2 in the // attr.Files if goVersion103OrAbove() { socket = "3" } else { socket = fmt.Sprintf("%v", srv.SocketFd()) } fmt.Printf("Forking now with socket: %v\n", socket) mypath := os.Args[0] args := []string{mypath, "-socket", socket} attr := new(syscall.ProcAttr) attr.Files = append([]uintptr(nil), 0, 1, 2, uintptr(srv.SocketFd())) pid, err = syscall.ForkExec(mypath, args, attr) return }
// setup and fork/exec myself. Make sure to keep open important FD's that won't get re-created by the child // specifically, std* and your listen socket func forker(srv *falcore.Server) (pid int, err error) { fmt.Printf("Forking now with socket: %v\n", srv.SocketFd()) mypath := os.Args[0] args := []string{mypath, "-socket", fmt.Sprintf("%v", srv.SocketFd())} attr := new(syscall.ProcAttr) attr.Files = append([]uintptr(nil), 0, 1, 2, uintptr(srv.SocketFd())) pid, err = syscall.ForkExec(mypath, args, attr) return }
// serveLandingPage is a testing helper function that creates a webserver that // other tests for NewPassthruFilter can use to verify expected proxying // behaviors. func serveLandingPage(landingServer *falcore.Server) { err := landingServer.ListenAndServe() if err != nil { panic(err) } }