code.gitea.io/gitea@v1.19.3/modules/graceful/server_hooks.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package graceful 5 6 import ( 7 "os" 8 "runtime" 9 10 "code.gitea.io/gitea/modules/log" 11 ) 12 13 // awaitShutdown waits for the shutdown signal from the Manager 14 func (srv *Server) awaitShutdown() { 15 select { 16 case <-GetManager().IsShutdown(): 17 // Shutdown 18 srv.doShutdown() 19 case <-GetManager().IsHammer(): 20 // Hammer 21 srv.doShutdown() 22 srv.doHammer() 23 } 24 <-GetManager().IsHammer() 25 srv.doHammer() 26 } 27 28 // shutdown closes the listener so that no new connections are accepted 29 // and starts a goroutine that will hammer (stop all running requests) the server 30 // after setting.GracefulHammerTime. 31 func (srv *Server) doShutdown() { 32 // only shutdown if we're running. 33 if srv.getState() != stateRunning { 34 return 35 } 36 37 srv.setState(stateShuttingDown) 38 39 if srv.OnShutdown != nil { 40 srv.OnShutdown() 41 } 42 err := srv.listener.Close() 43 if err != nil { 44 log.Error("PID: %d Listener.Close() error: %v", os.Getpid(), err) 45 } else { 46 log.Info("PID: %d Listener (%s) closed.", os.Getpid(), srv.listener.Addr()) 47 } 48 } 49 50 func (srv *Server) doHammer() { 51 defer func() { 52 // We call srv.wg.Done() until it panics. 53 // This happens if we call Done() when the WaitGroup counter is already at 0 54 // So if it panics -> we're done, Serve() will return and the 55 // parent will goroutine will exit. 56 if r := recover(); r != nil { 57 log.Error("WaitGroup at 0: Error: %v", r) 58 } 59 }() 60 if srv.getState() != stateShuttingDown { 61 return 62 } 63 log.Warn("Forcefully shutting down parent") 64 for { 65 if srv.getState() == stateTerminate { 66 break 67 } 68 srv.wg.Done() 69 70 // Give other goroutines a chance to finish before we forcibly stop them. 71 runtime.Gosched() 72 } 73 }