You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

server_hooks.go 1.8KB

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