"os"
"strings"
+ "code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/routers"
log.Critical("Failed to start server: %v", err)
}
log.Info("HTTP Listener: %s Closed", listenAddr)
+ graceful.WaitForServers()
log.Close()
return nil
}
"os"
"os/exec"
"strings"
+ "sync"
+ "syscall"
)
+var killParent sync.Once
+
+// KillParent sends the kill signal to the parent process if we are a child
+func KillParent() {
+ killParent.Do(func() {
+ if IsChild {
+ ppid := syscall.Getppid()
+ if ppid > 1 {
+ _ = syscall.Kill(ppid, syscall.SIGTERM)
+ }
+ }
+ })
+}
+
// RestartProcess starts a new process passing it the active listeners. It
// doesn't fork, but starts a new process using the same environment and
// arguments as when it was originally started. This allows for a newly
var (
// RWMutex for when adding servers or shutting down
runningServerReg sync.RWMutex
+ runningServerWG sync.WaitGroup
// ensure we only fork once
runningServersForked bool
func init() {
runningServerReg = sync.RWMutex{}
+ runningServerWG = sync.WaitGroup{}
DefaultMaxHeaderBytes = 0 // use http.DefaultMaxHeaderBytes - which currently is 1 << 20 (1MB)
}
OnShutdown func()
}
+// WaitForServers waits for all running servers to finish
+func WaitForServers() {
+ runningServerWG.Wait()
+}
+
// NewServer creates a server on network at provided address
func NewServer(network, address string) *Server {
runningServerReg.Lock()
srv.listener = newWrappedListener(l, srv)
- if IsChild {
- _ = syscall.Kill(syscall.Getppid(), syscall.SIGTERM)
- }
+ KillParent()
srv.BeforeBegin(srv.network, srv.address)
wl := newWrappedListener(l, srv)
srv.listener = tls.NewListener(wl, tlsConfig)
- if IsChild {
- _ = syscall.Kill(syscall.Getppid(), syscall.SIGTERM)
- }
+ KillParent()
srv.BeforeBegin(srv.network, srv.address)
return srv.Serve(serve)
func (srv *Server) Serve(serve ServeFunction) error {
defer log.Debug("Serve() returning... (PID: %d)", syscall.Getpid())
srv.setState(stateRunning)
+ runningServerWG.Add(1)
err := serve(srv.listener)
log.Debug("Waiting for connections to finish... (PID: %d)", syscall.Getpid())
srv.wg.Wait()
srv.setState(stateTerminate)
+ runningServerWG.Done()
// use of closed means that the listeners are closed - i.e. we should be shutting down - return nil
if err != nil && strings.Contains(err.Error(), "use of closed") {
return nil