Skip to content

Commit acc307e

Browse files
authored
fix: catch errors thrown during handleBeginFrame and handleDrawFrame (#2446)
* fix * update CHANGELOG * rethrow in automatedTestMode
1 parent 05933ac commit acc307e

File tree

3 files changed

+73
-8
lines changed

3 files changed

+73
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252

5353
### Fixes
5454

55+
- Catch errors thrown during `handleBeginFrame` and `handleDrawFrame` ([#2446](https://github.com/getsentry/sentry-dart/pull/2446))
5556
- OS & device contexts missing on Windows ([#2439](https://github.com/getsentry/sentry-dart/pull/2439))
5657
- Native iOS/macOS SDK session didn't start after Flutter hot-restart ([#2452](https://github.com/getsentry/sentry-dart/pull/2452))
5758

flutter/lib/src/binding_wrapper.dart

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// ignore_for_file: invalid_use_of_internal_member
22

33
import 'package:flutter/foundation.dart';
4-
5-
import '../sentry_flutter.dart';
64
import 'package:flutter/widgets.dart';
75
import 'package:meta/meta.dart';
86

7+
import '../sentry_flutter.dart';
8+
99
/// The methods and properties are modelled after the the real binding class.
1010
@experimental
1111
class BindingWrapper {
@@ -88,6 +88,8 @@ mixin SentryWidgetsBindingMixin on WidgetsBinding {
8888
FrameTimingCallback? _frameTimingCallback;
8989
ClockProvider? _clock;
9090

91+
SentryOptions get _options => Sentry.currentHub.options;
92+
9193
@internal
9294
void registerFramesTracking(
9395
FrameTimingCallback callback, ClockProvider clock) {
@@ -108,7 +110,13 @@ mixin SentryWidgetsBindingMixin on WidgetsBinding {
108110

109111
@override
110112
void handleBeginFrame(Duration? rawTimeStamp) {
111-
_startTimestamp = _clock?.call();
113+
try {
114+
_startTimestamp = _clock?.call();
115+
} catch (_) {
116+
if (_options.automatedTestMode) {
117+
rethrow;
118+
}
119+
}
112120

113121
super.handleBeginFrame(rawTimeStamp);
114122
}
@@ -117,11 +125,17 @@ mixin SentryWidgetsBindingMixin on WidgetsBinding {
117125
void handleDrawFrame() {
118126
super.handleDrawFrame();
119127

120-
final endTimestamp = _clock?.call();
121-
if (_startTimestamp != null &&
122-
endTimestamp != null &&
123-
_startTimestamp!.isBefore(endTimestamp)) {
124-
_frameTimingCallback?.call(_startTimestamp!, endTimestamp);
128+
try {
129+
final endTimestamp = _clock?.call();
130+
if (_startTimestamp != null &&
131+
endTimestamp != null &&
132+
_startTimestamp!.isBefore(endTimestamp)) {
133+
_frameTimingCallback?.call(_startTimestamp!, endTimestamp);
134+
}
135+
} catch (_) {
136+
if (_options.automatedTestMode) {
137+
rethrow;
138+
}
125139
}
126140
}
127141
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:sentry_flutter/src/binding_wrapper.dart';
3+
4+
import 'binding.dart';
5+
6+
void main() {
7+
// Make sure whatever error happens during the frame processing we catch it
8+
// Otherwise it would disrupt the frame processing and freeze the UI
9+
group('$SentryWidgetsBindingMixin', () {
10+
late SentryAutomatedTestWidgetsFlutterBinding binding;
11+
12+
setUp(() {
13+
binding = SentryAutomatedTestWidgetsFlutterBinding.ensureInitialized();
14+
// reset state
15+
binding.removeFramesTracking();
16+
});
17+
18+
test('frame processing continues execution when clock throws', () {
19+
binding.registerFramesTracking(
20+
(_, __) {},
21+
() => throw Exception('Clock error'),
22+
);
23+
24+
expect(
25+
() {
26+
binding.handleBeginFrame(null);
27+
binding.handleDrawFrame();
28+
},
29+
returnsNormally,
30+
);
31+
});
32+
33+
test('frame processing execution when callback throws', () {
34+
binding.registerFramesTracking(
35+
(_, __) {
36+
throw Exception('Callback error');
37+
},
38+
() => DateTime.now(),
39+
);
40+
41+
expect(
42+
() {
43+
binding.handleBeginFrame(null);
44+
binding.handleDrawFrame();
45+
},
46+
returnsNormally,
47+
);
48+
});
49+
});
50+
}

0 commit comments

Comments
 (0)