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

manager_unix.go 3.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // +build !windows
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package graceful
  6. import (
  7. "errors"
  8. "os"
  9. "os/signal"
  10. "sync"
  11. "syscall"
  12. "time"
  13. "code.gitea.io/gitea/modules/log"
  14. "code.gitea.io/gitea/modules/setting"
  15. )
  16. type gracefulManager struct {
  17. isChild bool
  18. forked bool
  19. lock *sync.RWMutex
  20. state state
  21. shutdown chan struct{}
  22. hammer chan struct{}
  23. terminate chan struct{}
  24. runningServerWaitGroup sync.WaitGroup
  25. createServerWaitGroup sync.WaitGroup
  26. terminateWaitGroup sync.WaitGroup
  27. }
  28. func newGracefulManager() *gracefulManager {
  29. manager := &gracefulManager{
  30. isChild: len(os.Getenv(listenFDs)) > 0 && os.Getppid() > 1,
  31. lock: &sync.RWMutex{},
  32. }
  33. manager.createServerWaitGroup.Add(numberOfServersToCreate)
  34. manager.Run()
  35. return manager
  36. }
  37. func (g *gracefulManager) Run() {
  38. g.setState(stateRunning)
  39. go g.handleSignals()
  40. c := make(chan struct{})
  41. go func() {
  42. defer close(c)
  43. // Wait till we're done getting all of the listeners and then close
  44. // the unused ones
  45. g.createServerWaitGroup.Wait()
  46. // Ignore the error here there's not much we can do with it
  47. // They're logged in the CloseProvidedListeners function
  48. _ = CloseProvidedListeners()
  49. }()
  50. if setting.StartupTimeout > 0 {
  51. go func() {
  52. select {
  53. case <-c:
  54. return
  55. case <-g.IsShutdown():
  56. return
  57. case <-time.After(setting.StartupTimeout):
  58. log.Error("Startup took too long! Shutting down")
  59. g.doShutdown()
  60. }
  61. }()
  62. }
  63. }
  64. func (g *gracefulManager) handleSignals() {
  65. var sig os.Signal
  66. signalChannel := make(chan os.Signal, 1)
  67. signal.Notify(
  68. signalChannel,
  69. syscall.SIGHUP,
  70. syscall.SIGUSR1,
  71. syscall.SIGUSR2,
  72. syscall.SIGINT,
  73. syscall.SIGTERM,
  74. syscall.SIGTSTP,
  75. )
  76. pid := syscall.Getpid()
  77. for {
  78. sig = <-signalChannel
  79. switch sig {
  80. case syscall.SIGHUP:
  81. if setting.GracefulRestartable {
  82. log.Info("PID: %d. Received SIGHUP. Forking...", pid)
  83. err := g.doFork()
  84. if err != nil && err.Error() != "another process already forked. Ignoring this one" {
  85. log.Error("Error whilst forking from PID: %d : %v", pid, err)
  86. }
  87. } else {
  88. log.Info("PID: %d. Received SIGHUP. Not set restartable. Shutting down...", pid)
  89. g.doShutdown()
  90. }
  91. case syscall.SIGUSR1:
  92. log.Info("PID %d. Received SIGUSR1.", pid)
  93. case syscall.SIGUSR2:
  94. log.Warn("PID %d. Received SIGUSR2. Hammering...", pid)
  95. g.doHammerTime(0 * time.Second)
  96. case syscall.SIGINT:
  97. log.Warn("PID %d. Received SIGINT. Shutting down...", pid)
  98. g.doShutdown()
  99. case syscall.SIGTERM:
  100. log.Warn("PID %d. Received SIGTERM. Shutting down...", pid)
  101. g.doShutdown()
  102. case syscall.SIGTSTP:
  103. log.Info("PID %d. Received SIGTSTP.", pid)
  104. default:
  105. log.Info("PID %d. Received %v.", pid, sig)
  106. }
  107. }
  108. }
  109. func (g *gracefulManager) doFork() error {
  110. g.lock.Lock()
  111. if g.forked {
  112. g.lock.Unlock()
  113. return errors.New("another process already forked. Ignoring this one")
  114. }
  115. g.forked = true
  116. g.lock.Unlock()
  117. // We need to move the file logs to append pids
  118. setting.RestartLogsWithPIDSuffix()
  119. _, err := RestartProcess()
  120. return err
  121. }
  122. func (g *gracefulManager) RegisterServer() {
  123. KillParent()
  124. g.runningServerWaitGroup.Add(1)
  125. }