11// Copyright 2022 MongoDB, Inc.
22// SPDX-License-Identifier: Apache-2.0
33
4+ import 'dart:async' ;
45import 'dart:ffi' ;
56import 'dart:isolate' ;
67import 'package:realm_dart/src/logging.dart' ;
@@ -20,25 +21,36 @@ class Scheduler {
2021
2122 Scheduler ._() {
2223 _receivePortFinalizer.attach (this , _receivePort, detach: this );
23-
24- _receivePort.handler = (dynamic message) {
25- if (message is List ) {
26- // currently the only `message as List` is from the logger.
27- final category = LogCategory .fromString (message[0 ] as String );
28- final level = LogLevel .values[message[1 ] as int ];
29- final text = message[2 ] as String ;
30- Realm .logger.raise ((category: category, level: level, message: text));
31- } else if (message is int ) {
32- realmCore.invokeScheduler (message);
33- } else {
34- Realm .logger.log (LogLevel .error, 'Unexpected Scheduler message type: ${message .runtimeType } - $message ' );
35- }
36- };
37-
24+ // There be dragons here!!!
25+ //
26+ // As of Dart 3.4 (Flutter 3.22) we started seeing uncaught exceptions on
27+ // the receivePort handler (issue #1676), stating that:
28+ // "argument value for 'return_value' is null" in
29+ // RealmLibrary.realm_scheduler_perform_work, but obviously a void method
30+ // don't return anything, so this is really a Dart issue.
31+ //
32+ // However, by ensuring the callback happens in the current zone (as it
33+ // rightfully should), and using bindUnaryCallbackGuarded, we can avoid
34+ // these.
35+ _receivePort.handler = Zone .current.bindUnaryCallbackGuarded (_handle);
3836 final sendPort = _receivePort.sendPort;
3937 handle = realmCore.createScheduler (Isolate .current.hashCode, sendPort.nativePort);
4038 }
4139
40+ void _handle (dynamic message) {
41+ if (message is List ) {
42+ // currently the only `message as List` is from the logger.
43+ final category = LogCategory .fromString (message[0 ] as String );
44+ final level = LogLevel .values[message[1 ] as int ];
45+ final text = message[2 ] as String ;
46+ Realm .logger.raise ((category: category, level: level, message: text));
47+ } else if (message is int ) {
48+ realmCore.invokeScheduler (message);
49+ } else {
50+ Realm .logger.log (LogLevel .error, 'Unexpected Scheduler message type: ${message .runtimeType } - $message ' );
51+ }
52+ }
53+
4254 void stop () {
4355 if (handle.released) {
4456 return ;
0 commit comments