From f301f311e8d5c4f6c4d4a165ef126ee5a092e8fa Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:52:29 +0900 Subject: [PATCH 1/3] fix --- lib/src/support/disposable.dart | 6 ++++- test/support/disposable_test.dart | 44 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 test/support/disposable_test.dart diff --git a/lib/src/support/disposable.dart b/lib/src/support/disposable.dart index 77c90c89..5d1ebeb5 100644 --- a/lib/src/support/disposable.dart +++ b/lib/src/support/disposable.dart @@ -39,7 +39,11 @@ mixin _Disposer { logger.finer('[$objectId] running ${_disposeFuncs.length} dispose funcs...'); // call dispose funcs in reverse order for (final disposeFunc in _disposeFuncs.reversed) { - await disposeFunc(); + try { + await disposeFunc(); + } catch (e, stack) { + logger.warning('[$objectId] error during dispose: $e', e, stack); + } } _disposeFuncs.clear(); logger.finer('[$objectId] dispose complete.'); diff --git a/test/support/disposable_test.dart b/test/support/disposable_test.dart new file mode 100644 index 00000000..c70fcb51 --- /dev/null +++ b/test/support/disposable_test.dart @@ -0,0 +1,44 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:livekit_client/src/support/disposable.dart'; + +class TestDisposable extends Disposable { + @override + Future dispose() async { + return await super.dispose(); + } +} + +void main() { + group('Disposable', () { + test('should execute all dispose functions even if one fails', () async { + final disposable = TestDisposable(); + bool func1Called = false; + bool func2Called = false; + bool func3Called = false; + + // Dispose functions are called in reverse order of addition + + // Added 1st -> Called 3rd + disposable.onDispose(() async { + func1Called = true; + }); + + // Added 2nd -> Called 2nd + disposable.onDispose(() async { + func2Called = true; + throw Exception('fail'); + }); + + // Added 3rd -> Called 1st + disposable.onDispose(() async { + func3Called = true; + }); + + await disposable.dispose(); + + expect(func3Called, isTrue, reason: 'Last added (func3) should be called first'); + expect(func2Called, isTrue, reason: 'Middle added (func2) should be called'); + expect(func1Called, isTrue, reason: 'First added (func1) should be called even if func2 failed'); + }); + }); +} From 6d586a3d7b258ae07fed2ccb4de064d3eb78907b Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:54:38 +0900 Subject: [PATCH 2/3] changes --- .changes/ensure-disposal-completion | 1 + 1 file changed, 1 insertion(+) create mode 100644 .changes/ensure-disposal-completion diff --git a/.changes/ensure-disposal-completion b/.changes/ensure-disposal-completion new file mode 100644 index 00000000..f1f20f85 --- /dev/null +++ b/.changes/ensure-disposal-completion @@ -0,0 +1 @@ +patch type="fixed" "Ensure all dispose functions are executed even if one throws" From bbf90d39599207e461e54b1845c8b5f91a1405b5 Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:59:54 +0900 Subject: [PATCH 3/3] fix sorter check --- test/support/disposable_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/test/support/disposable_test.dart b/test/support/disposable_test.dart index c70fcb51..306cfe05 100644 --- a/test/support/disposable_test.dart +++ b/test/support/disposable_test.dart @@ -1,4 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; + import 'package:livekit_client/src/support/disposable.dart'; class TestDisposable extends Disposable {