Skip to content

Commit db96f8f

Browse files
authored
Minor disposer improvement (#949)
Ensure all dispose functions are executed even if one throws.
1 parent 8e148f1 commit db96f8f

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
patch type="fixed" "Ensure all dispose functions are executed even if one throws"

lib/src/support/disposable.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ mixin _Disposer {
3939
logger.finer('[$objectId] running ${_disposeFuncs.length} dispose funcs...');
4040
// call dispose funcs in reverse order
4141
for (final disposeFunc in _disposeFuncs.reversed) {
42-
await disposeFunc();
42+
try {
43+
await disposeFunc();
44+
} catch (e, stack) {
45+
logger.warning('[$objectId] error during dispose: $e', e, stack);
46+
}
4347
}
4448
_disposeFuncs.clear();
4549
logger.finer('[$objectId] dispose complete.');

test/support/disposable_test.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
3+
import 'package:livekit_client/src/support/disposable.dart';
4+
5+
class TestDisposable extends Disposable {
6+
@override
7+
Future<bool> dispose() async {
8+
return await super.dispose();
9+
}
10+
}
11+
12+
void main() {
13+
group('Disposable', () {
14+
test('should execute all dispose functions even if one fails', () async {
15+
final disposable = TestDisposable();
16+
bool func1Called = false;
17+
bool func2Called = false;
18+
bool func3Called = false;
19+
20+
// Dispose functions are called in reverse order of addition
21+
22+
// Added 1st -> Called 3rd
23+
disposable.onDispose(() async {
24+
func1Called = true;
25+
});
26+
27+
// Added 2nd -> Called 2nd
28+
disposable.onDispose(() async {
29+
func2Called = true;
30+
throw Exception('fail');
31+
});
32+
33+
// Added 3rd -> Called 1st
34+
disposable.onDispose(() async {
35+
func3Called = true;
36+
});
37+
38+
await disposable.dispose();
39+
40+
expect(func3Called, isTrue, reason: 'Last added (func3) should be called first');
41+
expect(func2Called, isTrue, reason: 'Middle added (func2) should be called');
42+
expect(func1Called, isTrue, reason: 'First added (func1) should be called even if func2 failed');
43+
});
44+
});
45+
}

0 commit comments

Comments
 (0)