mirror of https://github.com/jetkvm/kvm.git
reconfigure display on native restart
This commit is contained in:
parent
91d3b47ec3
commit
afd8ab75bc
|
|
@ -232,6 +232,14 @@ func updateStaticContents() {
|
|||
// nativeInstance.UpdateLabelAndChangeVisibility("boot_screen_device_id", GetDeviceID())
|
||||
}
|
||||
|
||||
// configureDisplayOnNativeRestart is called when the native process restarts
|
||||
// it ensures the display is configured correctly after the restart
|
||||
func configureDisplayOnNativeRestart() {
|
||||
displayLogger.Info().Msg("native restarted, configuring display")
|
||||
updateStaticContents()
|
||||
requestDisplayUpdate(true, "native_restart")
|
||||
}
|
||||
|
||||
// setDisplayBrightness sets /sys/class/backlight/backlight/brightness to alter
|
||||
// the backlight brightness of the JetKVM hardware's display.
|
||||
func setDisplayBrightness(brightness int, reason string) error {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/erikdubbelboer/gspt"
|
||||
"github.com/rs/zerolog"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
|
@ -160,6 +159,9 @@ func (s *grpcServer) VideoLogStatus(ctx context.Context, req *pb.Empty) (*pb.Vid
|
|||
}
|
||||
|
||||
func (s *grpcServer) VideoStop(ctx context.Context, req *pb.Empty) (*pb.Empty, error) {
|
||||
procPrefix = "jetkvm: [native]"
|
||||
setProcTitle(lastProcTitle)
|
||||
|
||||
if err := s.native.VideoStop(); err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
|
@ -167,6 +169,9 @@ func (s *grpcServer) VideoStop(ctx context.Context, req *pb.Empty) (*pb.Empty, e
|
|||
}
|
||||
|
||||
func (s *grpcServer) VideoStart(ctx context.Context, req *pb.Empty) (*pb.Empty, error) {
|
||||
procPrefix = "jetkvm: [native+video]"
|
||||
setProcTitle(lastProcTitle)
|
||||
|
||||
if err := s.native.VideoStart(); err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
|
@ -315,7 +320,8 @@ func (s *grpcServer) DoNotUseThisIsForCrashTestingOnly(ctx context.Context, req
|
|||
|
||||
// StreamEvents streams events from the native process
|
||||
func (s *grpcServer) StreamEvents(req *pb.Empty, stream pb.NativeService_StreamEventsServer) error {
|
||||
gspt.SetProcTitle("jetkvm: [native] connected")
|
||||
setProcTitle("connected")
|
||||
defer setProcTitle("waiting")
|
||||
|
||||
eventCh := make(chan *pb.Event, 100)
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ type NativeOptions struct {
|
|||
OnVideoFrameReceived func(frame []byte, duration time.Duration)
|
||||
OnIndevEvent func(event string)
|
||||
OnRpcEvent func(event string)
|
||||
OnNativeRestart func()
|
||||
}
|
||||
|
||||
func NewNative(opts NativeOptions) *Native {
|
||||
|
|
|
|||
|
|
@ -33,11 +33,13 @@ type nativeProxyOptions struct {
|
|||
BinaryPath string `env:"JETKVM_NATIVE_BINARY_PATH"`
|
||||
LoggerLevel zerolog.Level `env:"JETKVM_NATIVE_LOGGER_LEVEL"`
|
||||
HandshakeMessage string `env:"JETKVM_NATIVE_HANDSHAKE_MESSAGE"`
|
||||
MaxRestartAttempts uint
|
||||
|
||||
OnVideoFrameReceived func(frame []byte, duration time.Duration)
|
||||
OnIndevEvent func(event string)
|
||||
OnRpcEvent func(event string)
|
||||
OnVideoStateChange func(state VideoState)
|
||||
OnNativeRestart func()
|
||||
}
|
||||
|
||||
func randomId(binaryLength int) string {
|
||||
|
|
@ -63,6 +65,7 @@ func (n *NativeOptions) toProxyOptions() *nativeProxyOptions {
|
|||
OnIndevEvent: n.OnIndevEvent,
|
||||
OnRpcEvent: n.OnRpcEvent,
|
||||
OnVideoStateChange: n.OnVideoStateChange,
|
||||
OnNativeRestart: n.OnNativeRestart,
|
||||
HandshakeMessage: handshakeMessage,
|
||||
}
|
||||
}
|
||||
|
|
@ -118,6 +121,7 @@ type NativeProxy struct {
|
|||
ready chan struct{}
|
||||
options *nativeProxyOptions
|
||||
restartM sync.Mutex
|
||||
restarts uint
|
||||
stopped bool
|
||||
processWait chan error
|
||||
}
|
||||
|
|
@ -142,10 +146,7 @@ func NewNativeProxy(opts NativeOptions) (*NativeProxy, error) {
|
|||
ready: make(chan struct{}),
|
||||
options: proxyOptions,
|
||||
processWait: make(chan error, 1),
|
||||
}
|
||||
proxy.cmd, err = proxy.toProcessCommand()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create process: %w", err)
|
||||
restarts: 0,
|
||||
}
|
||||
|
||||
return proxy, nil
|
||||
|
|
@ -195,6 +196,7 @@ func (w *nativeProxyStdoutHandler) Write(p []byte) (n int, err error) {
|
|||
if !w.handshakeDone && strings.Contains(string(p), w.handshakeMessage) {
|
||||
w.handshakeDone = true
|
||||
w.handshakeCh <- true
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
os.Stdout.Write(p)
|
||||
|
|
@ -287,6 +289,11 @@ func (p *NativeProxy) setUpGRPCClient() error {
|
|||
return fmt.Errorf("failed to wait for ready: %w", err)
|
||||
}
|
||||
|
||||
// Call on native restart callback if it exists and restarts are greater than 0
|
||||
if p.options.OnNativeRestart != nil && p.restarts > 0 {
|
||||
p.options.OnNativeRestart()
|
||||
}
|
||||
|
||||
// Start monitoring process for crashes
|
||||
go p.monitorProcess()
|
||||
return nil
|
||||
|
|
@ -298,6 +305,13 @@ func (p *NativeProxy) start() error {
|
|||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
cmd, err := p.toProcessCommand()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create process: %w", err)
|
||||
}
|
||||
|
||||
p.cmd = cmd
|
||||
|
||||
if err := p.cmd.Start(); err != nil {
|
||||
return fmt.Errorf("failed to start native process: %w", err)
|
||||
}
|
||||
|
|
@ -390,6 +404,8 @@ func (p *NativeProxy) restartProcess() error {
|
|||
_ = p.client.Close()
|
||||
}
|
||||
|
||||
p.restarts++
|
||||
|
||||
if err := p.start(); err != nil {
|
||||
return fmt.Errorf("failed to start native process: %w", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,24 +16,37 @@ import (
|
|||
// stdout - exchange messages with the parent process
|
||||
// stderr - logging and error messages
|
||||
|
||||
var (
|
||||
procPrefix string = "jetkvm: [native]"
|
||||
lastProcTitle string
|
||||
)
|
||||
|
||||
func setProcTitle(status string) {
|
||||
lastProcTitle = status
|
||||
if status != "" {
|
||||
status = " " + status
|
||||
}
|
||||
title := fmt.Sprintf("%s%s", procPrefix, status)
|
||||
gspt.SetProcTitle(title)
|
||||
}
|
||||
|
||||
// RunNativeProcess runs the native process mode
|
||||
func RunNativeProcess(binaryName string) {
|
||||
logger := *nativeLogger
|
||||
// Initialize logger
|
||||
|
||||
gspt.SetProcTitle("jetkvm: [native] starting")
|
||||
logger := nativeLogger.With().Int("pid", os.Getpid()).Logger()
|
||||
setProcTitle("starting")
|
||||
|
||||
// Parse native options
|
||||
var proxyOptions nativeProxyOptions
|
||||
if err := env.Parse(&proxyOptions); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to parse native options")
|
||||
logger.Fatal().Err(err).Msg("failed to parse native proxy options")
|
||||
}
|
||||
|
||||
// connect to video stream socket
|
||||
// Connect to video stream socket
|
||||
conn, err := net.Dial("unixpacket", proxyOptions.VideoStreamUnixSocket)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to connect to video stream socket")
|
||||
}
|
||||
logger.Info().Str("video_stream_socket_path", proxyOptions.VideoStreamUnixSocket).Msg("connected to video stream socket")
|
||||
logger.Info().Str("videoStreamSocketPath", proxyOptions.VideoStreamUnixSocket).Msg("connected to video stream socket")
|
||||
|
||||
nativeOptions := proxyOptions.toNativeOptions()
|
||||
nativeOptions.OnVideoFrameReceived = func(frame []byte, duration time.Duration) {
|
||||
|
|
@ -52,9 +65,10 @@ func RunNativeProcess(binaryName string) {
|
|||
logger.Fatal().Err(err).Msg("failed to start native instance")
|
||||
}
|
||||
|
||||
gspt.SetProcTitle("jetkvm: [native] starting gRPC server")
|
||||
grpcLogger := logger.With().Str("socketPath", fmt.Sprintf("@%v", proxyOptions.CtrlUnixSocket)).Logger()
|
||||
setProcTitle("starting gRPC server")
|
||||
// Create gRPC server
|
||||
grpcServer := NewGRPCServer(nativeInstance, &logger)
|
||||
grpcServer := NewGRPCServer(nativeInstance, &grpcLogger)
|
||||
|
||||
logger.Info().Msg("starting gRPC server")
|
||||
// Start gRPC server
|
||||
|
|
@ -62,7 +76,7 @@ func RunNativeProcess(binaryName string) {
|
|||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to start gRPC server")
|
||||
}
|
||||
gspt.SetProcTitle("jetkvm: [native] ready")
|
||||
setProcTitle("ready")
|
||||
|
||||
// Signal that we're ready by writing handshake message to stdout (for parent to read)
|
||||
// Stdout.Write is used to avoid buffering the message
|
||||
|
|
@ -76,8 +90,10 @@ func RunNativeProcess(binaryName string) {
|
|||
signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
|
||||
|
||||
// Wait for signal
|
||||
<-sigChan
|
||||
logger.Info().Msg("received termination signal")
|
||||
sig := <-sigChan
|
||||
logger.Info().
|
||||
Str("signal", sig.String()).
|
||||
Msg("received termination signal")
|
||||
|
||||
// Graceful shutdown
|
||||
server.GracefulStop()
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ func initNative(systemVersion *semver.Version, appVersion *semver.Version) {
|
|||
AppVersion: appVersion,
|
||||
DisplayRotation: config.GetDisplayRotation(),
|
||||
DefaultQualityFactor: config.VideoQualityFactor,
|
||||
OnNativeRestart: func() {
|
||||
configureDisplayOnNativeRestart()
|
||||
},
|
||||
OnVideoStateChange: func(state native.VideoState) {
|
||||
lastVideoState = state
|
||||
triggerVideoStateUpdate()
|
||||
|
|
|
|||
Loading…
Reference in New Issue