summaryrefslogtreecommitdiffstats
path: root/modules/graceful/server_signals.go
blob: d0013b77af052135be7a8d50084aab2c3d5c5849 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// +build !windows

// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package graceful

import (
	"os"
	"os/signal"
	"syscall"
	"time"

	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/setting"
)

var hookableSignals []os.Signal

func init() {
	hookableSignals = []os.Signal{
		syscall.SIGHUP,
		syscall.SIGUSR1,
		syscall.SIGUSR2,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGTSTP,
	}
}

// handleSignals listens for os Signals and calls any hooked in function that the
// user had registered with the signal.
func (srv *Server) handleSignals() {
	var sig os.Signal

	signal.Notify(
		srv.sigChan,
		hookableSignals...,
	)

	pid := syscall.Getpid()
	for {
		sig = <-srv.sigChan
		srv.preSignalHooks(sig)
		switch sig {
		case syscall.SIGHUP:
			if setting.GracefulRestartable {
				log.Info("PID: %d. Received SIGHUP. Forking...", pid)
				err := srv.fork()
				if err != nil {
					log.Error("Error whilst forking from PID: %d : %v", pid, err)
				}
			} else {
				log.Info("PID: %d. Received SIGHUP. Not set restartable. Shutting down...", pid)

				srv.shutdown()
			}
		case syscall.SIGUSR1:
			log.Info("PID %d. Received SIGUSR1.", pid)
		case syscall.SIGUSR2:
			log.Warn("PID %d. Received SIGUSR2. Hammering...", pid)
			srv.hammerTime(0 * time.Second)
		case syscall.SIGINT:
			log.Warn("PID %d. Received SIGINT. Shutting down...", pid)
			srv.shutdown()
		case syscall.SIGTERM:
			log.Warn("PID %d. Received SIGTERM. Shutting down...", pid)
			srv.shutdown()
		case syscall.SIGTSTP:
			log.Info("PID %d. Received SIGTSTP.")
		default:
			log.Info("PID %d. Received %v.", sig)
		}
		srv.postSignalHooks(sig)
	}
}

func (srv *Server) preSignalHooks(sig os.Signal) {
	if _, notSet := srv.PreSignalHooks[sig]; !notSet {
		return
	}
	for _, f := range srv.PreSignalHooks[sig] {
		f()
	}
}

func (srv *Server) postSignalHooks(sig os.Signal) {
	if _, notSet := srv.PostSignalHooks[sig]; !notSet {
		return
	}
	for _, f := range srv.PostSignalHooks[sig] {
		f()
	}
}