-
Notifications
You must be signed in to change notification settings - Fork 246
feat: failsafe mode #952
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
feat: failsafe mode #952
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
fb3e57a
feat: implement fail-safe mode UI
adamshiervani fc7156f
fix: remove unused variable from FailSafeModeOverlay component
adamshiervani 2c512f7
chore: comment out failsafe mode timeout in KvmIdRoute component
adamshiervani 42a0e1f
refactor: update FailSafeModeOverlay to simplify reboot handling and …
adamshiervani 6afb15b
chore: comment out failsafe mode timeout in KvmIdRoute component
adamshiervani 239c2dc
chore: backport supervisor changes
ym 03ab8d8
feat: add failsafe mode to recover from infinite restarts caused by c…
ym 99a6012
feat: add failsafe mode to recover from infinite restarts caused by c…
ym 72f29df
fix: ignore errors when crash log doesn't exist
ym 82ad2a4
feat: enhance FailSafeModeOverlay with tooltip and log download impro…
adamshiervani 5933adb
feat: implement FailSafeModeOverlay component with log download and i…
adamshiervani 502cd4e
fix: handle mDNS initialization error without exiting the application
adamshiervani 6b052e7
Update ui/src/components/FailSafeModeOverlay.tsx
ym 9115362
chore: make downgrade version configurable
ym 426cd6f
fix: update KvmIdRoute to conditionally render WebRTCVideo based on f…
adamshiervani bbbea61
fix: simplify tooltip text in FailSafeModeOverlay for clarity
adamshiervani 029a78e
fix: update FailsafeModeState to ensure reason is always a string and…
adamshiervani 4def3e6
fix: adjust failsafe mode handling in KvmIdRoute to improve WebRTCVid…
adamshiervani b70199c
Revert "fix: adjust failsafe mode handling in KvmIdRoute to improve W…
adamshiervani d8e3140
fix: Proper logic for hiding the WebRTC Video stream
adamshiervani 8406a35
fix: reset failsafe mode on reboot
adamshiervani File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| package kvm | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "strings" | ||
| "sync" | ||
| ) | ||
|
|
||
| const ( | ||
| failsafeDefaultLastCrashPath = "/userdata/jetkvm/crashdump/last-crash.log" | ||
| failsafeFile = "/userdata/jetkvm/.enablefailsafe" | ||
| failsafeLastCrashEnv = "JETKVM_LAST_ERROR_PATH" | ||
| failsafeEnv = "JETKVM_FORCE_FAILSAFE" | ||
| ) | ||
|
|
||
| var ( | ||
| failsafeOnce sync.Once | ||
| failsafeCrashLog = "" | ||
| failsafeModeActive = false | ||
| failsafeModeReason = "" | ||
| ) | ||
|
|
||
| type FailsafeModeNotification struct { | ||
| Active bool `json:"active"` | ||
| Reason string `json:"reason"` | ||
| } | ||
|
|
||
| // this function has side effects and can be only executed once | ||
| func checkFailsafeReason() { | ||
| failsafeOnce.Do(func() { | ||
| // check if the failsafe environment variable is set | ||
| if os.Getenv(failsafeEnv) == "1" { | ||
| failsafeModeActive = true | ||
| failsafeModeReason = "failsafe_env_set" | ||
| return | ||
| } | ||
|
|
||
| // check if the failsafe file exists | ||
| if _, err := os.Stat(failsafeFile); err == nil { | ||
| failsafeModeActive = true | ||
| failsafeModeReason = "failsafe_file_exists" | ||
| _ = os.Remove(failsafeFile) | ||
ym marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return | ||
| } | ||
|
|
||
| // get the last crash log path from the environment variable | ||
| lastCrashPath := os.Getenv(failsafeLastCrashEnv) | ||
| if lastCrashPath == "" { | ||
| lastCrashPath = failsafeDefaultLastCrashPath | ||
| } | ||
|
|
||
| // check if the last crash log file exists | ||
| l := failsafeLogger.With().Str("path", lastCrashPath).Logger() | ||
| fi, err := os.Lstat(lastCrashPath) | ||
| if err != nil { | ||
| if !os.IsNotExist(err) { | ||
| l.Warn().Err(err).Msg("failed to stat last crash log") | ||
| } | ||
| return | ||
| } | ||
|
|
||
| if fi.Mode()&os.ModeSymlink != os.ModeSymlink { | ||
| l.Warn().Msg("last crash log is not a symlink, ignoring") | ||
| return | ||
| } | ||
|
|
||
| // open the last crash log file and find if it contains the string "panic" | ||
| content, err := os.ReadFile(lastCrashPath) | ||
| if err != nil { | ||
| l.Warn().Err(err).Msg("failed to read last crash log") | ||
| return | ||
| } | ||
|
|
||
| // unlink the last crash log file | ||
| failsafeCrashLog = string(content) | ||
| _ = os.Remove(lastCrashPath) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we delay trashing the crashlog until we've exited the failsafe mode through some action? |
||
|
|
||
| // TODO: read the goroutine stack trace and check which goroutine is panicking | ||
| if strings.Contains(failsafeCrashLog, "runtime.cgocall") { | ||
| failsafeModeActive = true | ||
| failsafeModeReason = "video" | ||
| return | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| func notifyFailsafeMode(session *Session) { | ||
| if !failsafeModeActive || session == nil { | ||
| return | ||
| } | ||
|
|
||
| jsonRpcLogger.Info().Str("reason", failsafeModeReason).Msg("sending failsafe mode notification") | ||
|
|
||
| writeJSONRPCEvent("failsafeMode", FailsafeModeNotification{ | ||
| Active: true, | ||
| Reason: failsafeModeReason, | ||
| }, session) | ||
| } | ||
|
|
||
| func rpcGetFailsafeLogs() (string, error) { | ||
| if !failsafeModeActive { | ||
| return "", fmt.Errorf("failsafe mode is not active") | ||
| } | ||
|
|
||
| return failsafeCrashLog, nil | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.