sigtrap_posix.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Copyright 2015 Light Code Labs, LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // +build !windows,!plan9,!nacl,!js
  15. package caddy
  16. import (
  17. "log"
  18. "os"
  19. "os/signal"
  20. "syscall"
  21. "github.com/caddyserver/caddy/telemetry"
  22. )
  23. // trapSignalsPosix captures POSIX-only signals.
  24. func trapSignalsPosix() {
  25. go func() {
  26. sigchan := make(chan os.Signal, 1)
  27. signal.Notify(sigchan, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGUSR1, syscall.SIGUSR2)
  28. for sig := range sigchan {
  29. switch sig {
  30. case syscall.SIGQUIT:
  31. log.Println("[INFO] SIGQUIT: Quitting process immediately")
  32. for _, f := range OnProcessExit {
  33. f() // only perform important cleanup actions
  34. }
  35. os.Exit(0)
  36. case syscall.SIGTERM:
  37. log.Println("[INFO] SIGTERM: Shutting down servers then terminating")
  38. exitCode := executeShutdownCallbacks("SIGTERM")
  39. for _, f := range OnProcessExit {
  40. f() // only perform important cleanup actions
  41. }
  42. err := Stop()
  43. if err != nil {
  44. log.Printf("[ERROR] SIGTERM stop: %v", err)
  45. exitCode = 3
  46. }
  47. telemetry.AppendUnique("sigtrap", "SIGTERM")
  48. go telemetry.StopEmitting() // won't finish in time, but that's OK - just don't block
  49. os.Exit(exitCode)
  50. case syscall.SIGUSR1:
  51. log.Println("[INFO] SIGUSR1: Reloading")
  52. go telemetry.AppendUnique("sigtrap", "SIGUSR1")
  53. // Start with the existing Caddyfile
  54. caddyfileToUse, inst, err := getCurrentCaddyfile()
  55. if err != nil {
  56. log.Printf("[ERROR] SIGUSR1: %v", err)
  57. continue
  58. }
  59. if loaderUsed.loader == nil {
  60. // This also should never happen
  61. log.Println("[ERROR] SIGUSR1: no Caddyfile loader with which to reload Caddyfile")
  62. continue
  63. }
  64. // Load the updated Caddyfile
  65. newCaddyfile, err := loaderUsed.loader.Load(inst.serverType)
  66. if err != nil {
  67. log.Printf("[ERROR] SIGUSR1: loading updated Caddyfile: %v", err)
  68. continue
  69. }
  70. if newCaddyfile != nil {
  71. caddyfileToUse = newCaddyfile
  72. }
  73. // Backup old event hooks
  74. oldEventHooks := cloneEventHooks()
  75. // Purge the old event hooks
  76. purgeEventHooks()
  77. // Kick off the restart; our work is done
  78. EmitEvent(InstanceRestartEvent, nil)
  79. _, err = inst.Restart(caddyfileToUse)
  80. if err != nil {
  81. restoreEventHooks(oldEventHooks)
  82. log.Printf("[ERROR] SIGUSR1: %v", err)
  83. }
  84. case syscall.SIGUSR2:
  85. log.Println("[INFO] SIGUSR2: Upgrading")
  86. go telemetry.AppendUnique("sigtrap", "SIGUSR2")
  87. if err := Upgrade(); err != nil {
  88. log.Printf("[ERROR] SIGUSR2: upgrading: %v", err)
  89. }
  90. case syscall.SIGHUP:
  91. // ignore; this signal is sometimes sent outside of the user's control
  92. go telemetry.AppendUnique("sigtrap", "SIGHUP")
  93. }
  94. }
  95. }()
  96. }