Skip to content

Commit ac28b1b

Browse files
committed
clean
1 parent 3f205b2 commit ac28b1b

3 files changed

Lines changed: 108 additions & 1 deletion

File tree

failsafe.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package kvm
2+
3+
import (
4+
"os"
5+
"strings"
6+
"sync"
7+
8+
"github.com/jetkvm/kvm/internal/supervisor"
9+
)
10+
11+
const (
12+
failsafeDefaultLastCrashPath = "/userdata/jetkvm/crashdump/last-crash.log"
13+
failsafeFile = "/userdata/jetkvm/.enablefailsafe"
14+
failsafeLastCrashEnv = "JETKVM_LAST_ERROR_PATH"
15+
failsafeEnv = "JETKVM_FORCE_FAILSAFE"
16+
)
17+
18+
var (
19+
failsafeOnce sync.Once
20+
failsafeCrashLog = ""
21+
failsafeModeActive = false
22+
failsafeModeReason = ""
23+
)
24+
25+
type FailsafeModeNotification struct {
26+
Active bool `json:"active"`
27+
Reason string `json:"reason"`
28+
}
29+
30+
// this function has side effects and can be only executed once
31+
func checkFailsafeReason() {
32+
failsafeOnce.Do(func() {
33+
// check if the failsafe environment variable is set
34+
if os.Getenv(failsafeEnv) == "1" {
35+
failsafeModeActive = true
36+
failsafeModeReason = "failsafe_env_set"
37+
return
38+
}
39+
40+
// check if the failsafe file exists
41+
if _, err := os.Stat(failsafeFile); err == nil {
42+
failsafeModeActive = true
43+
failsafeModeReason = "failsafe_file_exists"
44+
_ = os.Remove(failsafeFile)
45+
return
46+
}
47+
48+
// get the last crash log path from the environment variable
49+
lastCrashPath := os.Getenv(failsafeLastCrashEnv)
50+
if lastCrashPath == "" {
51+
lastCrashPath = failsafeDefaultLastCrashPath
52+
}
53+
54+
// check if the last crash log file exists
55+
l := failsafeLogger.With().Str("path", lastCrashPath).Logger()
56+
fi, err := os.Lstat(lastCrashPath)
57+
if err != nil {
58+
if !os.IsNotExist(err) {
59+
l.Warn().Err(err).Msg("failed to stat last crash log")
60+
}
61+
return
62+
}
63+
64+
if fi.Mode()&os.ModeSymlink != os.ModeSymlink {
65+
l.Warn().Msg("last crash log is not a symlink, ignoring")
66+
return
67+
}
68+
69+
// open the last crash log file and find if it contains the string "panic"
70+
content, err := os.ReadFile(lastCrashPath)
71+
if err != nil {
72+
l.Warn().Err(err).Msg("failed to read last crash log")
73+
return
74+
}
75+
76+
// unlink the last crash log file
77+
failsafeCrashLog = string(content)
78+
_ = os.Remove(lastCrashPath)
79+
80+
// TODO: read the goroutine stack trace and check which goroutine is panicking
81+
failsafeModeActive = true
82+
if strings.Contains(failsafeCrashLog, supervisor.FailsafeReasonVideoMaxRestartAttemptsReached) {
83+
failsafeModeReason = "video"
84+
return
85+
}
86+
if strings.Contains(failsafeCrashLog, "runtime.cgocall") {
87+
failsafeModeReason = "video"
88+
return
89+
} else {
90+
failsafeModeReason = "unknown"
91+
}
92+
})
93+
}
94+
95+
func notifyFailsafeMode(session *Session) {
96+
if !failsafeModeActive || session == nil {
97+
return
98+
}
99+
100+
jsonRpcLogger.Info().Str("reason", failsafeModeReason).Msg("sending failsafe mode notification")
101+
102+
writeJSONRPCEvent("failsafeMode", FailsafeModeNotification{
103+
Active: true,
104+
Reason: failsafeModeReason,
105+
}, session)
106+
}

log.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ func ErrorfL(l *zerolog.Logger, format string, err error, args ...any) error {
1111

1212
var (
1313
logger = logging.GetSubsystemLogger("jetkvm")
14+
failsafeLogger = logging.GetSubsystemLogger("failsafe")
1415
networkLogger = logging.GetSubsystemLogger("network")
1516
cloudLogger = logging.GetSubsystemLogger("cloud")
1617
websocketLogger = logging.GetSubsystemLogger("websocket")

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func Main() {
3030

3131
logger.Log().Msg("JetKVM Starting Up")
3232

33-
initFailsafe()
33+
checkFailsafeReason()
3434
if failsafeModeActive {
3535
procPrefix = "jetkvm: [app+failsafe]"
3636
logger.Warn().Str("reason", failsafeModeReason).Msg("failsafe mode activated")

0 commit comments

Comments
 (0)