mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-10 06:21:02 +03:00
fix: address texture watchdog/probe review findings
- watchdog: compare the plugin's cumulative consumed counter against a snapshot taken when arming (re-arm was a no-op before), and judge on cumulative pushes + elapsed time so sparse damage-driven streams are still detected - failure handling is idempotent (one record per breakage) and updates every render session like main_set_local_option does, not only the failing one; the fallback toast is not claimed for multi-display windows the soft path cannot rescue - probe: skip when the consumed API is missing (old plugin) or a raster-stall is recorded (compositing could hang the main window); a fail verdict requires fresh frame timings and a non-minimized window; a pass never clears failed-raster-stall; toast only when texture rendering was effectively on; probe pixel is transparent - raster-stall monitor: judge on frame-timing staleness (a mid-episode hang was undetectable before), gate on lifecycle/minimized/idle with a moving quiet anchor, threshold 30s, shared with the camera page; clear stateGlobal minimized flag on plain window restore - adopt mismatched frame sizes only in multi-ui-session mode (legacy mode pairs frames loosely and could ping-pong between displays) - drop the now-dead closeSession parameter from texture destroy(); trim comments to repo style Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
52
flutter/lib/desktop/widgets/raster_stall_monitor.dart
Normal file
52
flutter/lib/desktop/widgets/raster_stall_monitor.dart
Normal file
@@ -0,0 +1,52 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
||||
import '../../common.dart';
|
||||
import '../../consts.dart';
|
||||
import '../../models/platform_model.dart';
|
||||
import '../../models/state_model.dart';
|
||||
|
||||
/// Records a hung raster thread (frames continuously scheduled but no frame
|
||||
/// timings delivered for 30s) in `texture-render-health`; a hang cannot be
|
||||
/// rescued in-process, so the next launch defaults texture rendering off.
|
||||
class RasterStallMonitor {
|
||||
static bool _started = false;
|
||||
static bool _reported = false;
|
||||
static DateTime? _lastTimings;
|
||||
static DateTime _lastQuiet = DateTime.now();
|
||||
|
||||
static void start() {
|
||||
if (_started || isWeb) return;
|
||||
_started = true;
|
||||
SchedulerBinding.instance.addTimingsCallback((_) {
|
||||
_lastTimings = DateTime.now();
|
||||
});
|
||||
Timer.periodic(const Duration(seconds: 2), (_) {
|
||||
if (_reported) return;
|
||||
final now = DateTime.now();
|
||||
final lifecycle = SchedulerBinding.instance.lifecycleState;
|
||||
// Minimized/inactive (incl. screen lock) or idle (nothing scheduled):
|
||||
// no timings is legitimate, keep moving the quiet anchor forward.
|
||||
if (stateGlobal.isMinimized ||
|
||||
(lifecycle != null && lifecycle != AppLifecycleState.resumed) ||
|
||||
!SchedulerBinding.instance.hasScheduledFrame) {
|
||||
_lastQuiet = now;
|
||||
return;
|
||||
}
|
||||
var ref = _lastQuiet;
|
||||
final lastTimings = _lastTimings;
|
||||
if (lastTimings != null && lastTimings.isAfter(ref)) {
|
||||
ref = lastTimings;
|
||||
}
|
||||
if (now.difference(ref) > const Duration(seconds: 30)) {
|
||||
_reported = true;
|
||||
bind.mainSetLocalOption(
|
||||
key: kOptionTextureRenderHealth, value: 'failed-raster-stall');
|
||||
debugPrint(
|
||||
'raster thread stall detected, texture rendering disabled for next launch');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user