-
Notifications
You must be signed in to change notification settings - Fork 262
Fix USB Gadget polling/writing to recover from errors #1035
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
base: dev
Are you sure you want to change the base?
Conversation
Remove duplicate logging. Moved the log helpers to internal/logging to share. Cleaned up usbGadget setup and tear down. Fixed active-session count mismatch on device screen. Cleaned up the usbGadget content comparisons. Enhance the usbgadget changeset management. Unmount images when shutting down. nmlite gateway add/remote are info, not warning. Made all the HID message structures loggable. Keep usbGadget Init from destroying the gadget. Clear the auto-release timers before cancelling the state poller. Made all gadget callbacks execute in their own goroutines and moved the USB state polling to after the callback setup. Attempt to reopen the KeyboardHidFile every time we check USB state and it's configured (will do nothing if already open). Made active session count atomic, without mutexes. Fixed tracing level check of HID Message Handler so Data is shown in Trace or Debug level. Fixed order of mount/ndb start/nbp stop/dismount to fix mount drive wonkiness. Protect the open of Keyboard HID file with mutex. Fix process for killing/copying/starting application Better logging Move ByteSlice to utils and added zerolog marshalling Exposed the UpdateConfigLogLevel Fixed the logging Updating the config would not change the logging until a reboot. Environment variables setting logging levels was broken. Caching the loggers prevent configuration changes from being effective because zerolog.Logger(s) are immutable. Added log level option to Advanced Settings menu
Also now can be logged as hex
Fix log level changes being reflected before a reboot Add tons of helpers for contextual logging Fix typo in relative mouse logging.
Made all call-backs go routines. Made listenKeyboardEvents callable as a go routine and returns when the keyboard file is closed/nil Cleaned up the auto-release to remove duplicate code. Moved to new logging helpers
Also restructured config_tx so it doesn't need copies of config data.
3137b60 to
bf436c5
Compare
Also restructured config_tx so it doesn't need copies of config data. Fuller debug logging in hidrpc and make all reportHidRPC sends async. Pass up errors from handleHidRPCMessage. listenKeyboardEvents handles closed keyboard file and terminates loop. Excess write failures cause close/open cycle Adds Settings menu to UI to allow setting the log level
4542b33 to
88f6b5c
Compare
Add missing types for enhancing context Also cleaned up the syntax to be more compact Expose the zerolog.Event for levels Ported synctrace and timesync
88f6b5c to
09eb984
Compare
| "github.com/jetkvm/kvm/internal/usbgadget" | ||
| ) | ||
|
|
||
| // MessageType is the type of the HID RPC message |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved this to message.go where it really makes more sense
| setProcTitle("ready") | ||
| mainLogger.Log().Msg("JetKVM ready") | ||
|
|
||
| go RunAutoUpdateCheck() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... no don't start up the AUP until we're fully ready...
| // if err != nil { | ||
| // logger.Infof("Failed to unmount fuse: %v", err) | ||
| // } | ||
| if err := rpcUnmountImage(); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have to unmount the drive or the UsbGadget gets wonky... and it takes reboot to get it back.
| mainLogger.Warn().Err(err).Msg("failed to eject virtual media on shutdown") | ||
| } | ||
|
|
||
| gadget.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explicitly close the gadget so we don't have all the "setup" still pretending the devices exist to the client
| return nil | ||
| } | ||
|
|
||
| func RunAutoUpdateCheck() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved here from the main
| if err := gadget.OpenKeyboardHidFile(); err != nil { | ||
| usbLogger.Error().Err(err).Msg("failed to open keyboard hid file") | ||
| } | ||
| go func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... and the MAIN REASON we're here...
We need to do this last and we need to do two things... one, return the gadget to the main so it can .Close() it... and two.... automatically reopen the keyboard HID file (which restarts the listeners) whenever the USB goes "ready"... so effectively this loop is where we notice the plug-in and "resume/start" the handling correctly.
NOTE: the open is basically a NOP if it was already open... and this loop is what reopens it if we close it on some error... kicking things back off... so we can when too many writes timeout, or when too many reads (for the LED state) just close the whole gadget down and open 'er back up to get past them unplug/replug of the USB
| URL: url, | ||
| Size: n, | ||
| } | ||
| virtualMediaStateMutex.Unlock() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dangled lock if we hit any errors in this method... ugh.
| err := syscall.Statfs(imagesFolder, &stat) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to get storage stats: %v", err) | ||
| return nil, fmt.Errorf("failed to get storage stats: %w", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Errorf likes %w to know it should unwrap the error for more detail (but NOT Msgf)
|
|
||
| actionSessions++ | ||
| return actionSessions | ||
| func incrActiveSessions() int32 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted... was seeing the session count get wonky... so just went atomic
Ported block_device/nbd Made the native CGO return distinct errors in set_edid Made the cgo_linux (go code) report C-level error return codes Use defer for server and listener cleanup. Try doing a timeboxed GracefulStop of the server
09eb984 to
0a1f463
Compare
a9d3809 to
272c0b0
Compare
272c0b0 to
55b0820
Compare
|
Can you factor these out to their own PR:
|
8ecc02c to
f8f6524
Compare
It's going to be a bit... the logging changes were kind of invasive and required to actually find the bugs. I will extract the "functional" fixed when I get a bit more time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 122 out of 123 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
internal/usbgadget/usbgadget.go:182
- File handle may be writable as a result of data flow from a call to OpenFile and closing it may result in data loss upon failure, which is not handled explicitly.
internal/usbgadget/usbgadget.go:186 - File handle may be writable as a result of data flow from a call to OpenFile and closing it may result in data loss upon failure, which is not handled explicitly.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
d50d832 to
4705dde
Compare
Fixes #128
Summary