mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-06-09 18:04:53 +03:00
fix(android): close session on dispose to prevent reconnect wedge (#15143)
RemotePage.dispose() only reaches sessionClose at the tail of gFFI.close(), behind several awaits (canvas save, image update, the enable_soft_keyboard platform call). If the app is backgrounded while the page is disposing, dispose can be suspended before that runs, so the session is never torn down. The next reconnect re-attaches to the leaked session (mobile reuses a constant sessionId) and is stuck on "Connecting..." forever while the orphaned io_loop keeps streaming. Dispatch sessionClose at the start of dispose so teardown happens synchronously on route pop, before backgrounding can interrupt it. The sessionClose in gFFI.close() becomes a no-op once the session is already removed. Fixes #15060 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -126,6 +126,14 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
|
||||
@override
|
||||
Future<void> dispose() async {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
// Close the session up-front. `gFFI.close()` below only calls `sessionClose`
|
||||
// after several awaits (canvas save, image update, the `enable_soft_keyboard`
|
||||
// platform call), so if the app is backgrounded while this page is disposing,
|
||||
// dispose can be suspended before reaching it and the connection is never torn
|
||||
// down. The reconnect then re-attaches to the leaked session and is stuck on
|
||||
// "Connecting...". Dispatching it here makes teardown happen synchronously on
|
||||
// pop; the `sessionClose` in `gFFI.close()` becomes a no-op once removed.
|
||||
unawaited(bind.sessionClose(sessionId: sessionId));
|
||||
// https://github.com/flutter/flutter/issues/64935
|
||||
super.dispose();
|
||||
gFFI.dialogManager.hideMobileActionsOverlay(store: false);
|
||||
|
||||
Reference in New Issue
Block a user