This repository has been archived by the owner on Oct 11, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
watchdog.go
114 lines (98 loc) · 2.65 KB
/
watchdog.go
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package main
import (
//Process management
"github.com/mitchellh/go-ps"
//std necessities
"os"
"os/exec"
"os/signal"
"path/filepath"
"strconv"
"syscall"
"time"
)
var sig1 = syscall.SIGINT
var sig2 = syscall.SIGKILL
var watchdogDelay = (5 * time.Second)
func doWatchdog() {
log.Trace("--- doWatchdog() ---")
log.Debug("Spawning initial bot process")
botPID := spawnBot()
log.Debug("Creating signal channel")
sc := make(chan os.Signal, 1)
log.Debug("Registering notification for ", sig1, " on signal channel")
signal.Notify(sc, sig1)
log.Debug("Registering notification for ", sig2, " on signal channel")
signal.Notify(sc, sig2)
log.Debug("Creating watchdog ticker for ", watchdogDelay)
watchdogTicker := time.Tick(watchdogDelay)
for {
select {
case <-watchdogTicker:
if !isProcessRunning(botPID) {
log.Debug("Failed to find process for bot PID ", botPID, ", spawning new bot process")
botPID = spawnBot()
}
case sig, ok := <-sc:
if ok {
log.Trace("SIGNAL: ", sig)
if isProcessRunning(botPID) {
log.Debug("Finding process for bot PID ", botPID)
botProcess, err := os.FindProcess(botPID)
if err == nil {
log.Debug("Sending ", sig, " signal to bot process")
_ = botProcess.Signal(sig)
log.Debug("Waiting for bot process to exit gracefully")
waitProcess(botPID)
}
}
log.Debug("Exiting")
os.Exit(0)
}
}
}
}
func spawnBot() int {
log.Trace("--- spawnBot() ---")
if killOldBot {
processList, err := ps.Processes()
if err == nil {
for _, process := range processList {
if process.Pid() != os.Getpid() && process.Pid() != watchdogPID && process.Executable() == filepath.Base(os.Args[0]) {
oldProcess, err := os.FindProcess(process.Pid())
if oldProcess != nil && err == nil {
oldProcess.Signal(syscall.SIGKILL)
}
}
}
}
}
botProcess := exec.Command(os.Args[0], "--isBot", "--watchdogPID", strconv.Itoa(os.Getpid()), "--verbosity", strconv.Itoa(verbosity), "--config", configFile)
botProcess.Stdout = os.Stdout
botProcess.Stderr = os.Stderr
botProcess.Stdin = os.Stdin
log.Debug("Spawning bot process")
err := botProcess.Start()
if err != nil {
panic(err)
}
log.Debug("Created bot process with PID ", botProcess.Process.Pid)
return botProcess.Process.Pid
}
func isProcessRunning(pid int) bool {
//log.Trace("--- isProcessRunning(pid: ", pid, ") ---")
process, err := ps.FindProcess(pid)
if err != nil {
log.Error(err)
return false
}
return process != nil
}
func waitProcess(pid int) {
log.Trace("--- waitProcess(pid: ", pid, ") ---")
process, err := os.FindProcess(pid)
if err != nil {
return
}
_, _ = process.Wait()
}