Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RDART-1028: Use Zone.current.bindUnaryCallbackGuarded for RawReceivePort.handler #1683

Merged
merged 3 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### Fixed
* Private fields did not work with default values. (Issue [#1663](https://github.com/realm/realm-dart/issues/1663))
* Invoke scheduler callback on Zone.current. (Issue [#1676](https://github.com/realm/realm-dart/issues/1676))

* Having links in a nested collections would leave the file inconsistent if the top object is removed. (Core 14.7.0)

Expand Down
42 changes: 27 additions & 15 deletions packages/realm_dart/lib/src/scheduler.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2022 MongoDB, Inc.
// SPDX-License-Identifier: Apache-2.0

import 'dart:async';
import 'dart:ffi';
import 'dart:isolate';
import 'package:realm_dart/src/logging.dart';
Expand All @@ -20,25 +21,36 @@ class Scheduler {

Scheduler._() {
_receivePortFinalizer.attach(this, _receivePort, detach: this);

_receivePort.handler = (dynamic message) {
if (message is List) {
// currently the only `message as List` is from the logger.
final category = LogCategory.fromString(message[0] as String);
final level = LogLevel.values[message[1] as int];
final text = message[2] as String;
Realm.logger.raise((category: category, level: level, message: text));
} else if (message is int) {
realmCore.invokeScheduler(message);
} else {
Realm.logger.log(LogLevel.error, 'Unexpected Scheduler message type: ${message.runtimeType} - $message');
}
};

// There be dragons here!!!
//
// As of Dart 3.4 (Flutter 3.22) we started seeing uncaught exceptions on
// the receivePort handler (issue #1676), stating that:
// "argument value for 'return_value' is null" in
// RealmLibrary.realm_scheduler_perform_work, but obviously a void method
// don't return anything, so this is really a Dart issue.
//
// However, by ensuring the callback happens in the current zone (as it
// rightfully should), and using bindUnaryCallbackGuarded, we can avoid
// these.
_receivePort.handler = Zone.current.bindUnaryCallbackGuarded(_handle);
nielsenko marked this conversation as resolved.
Show resolved Hide resolved
final sendPort = _receivePort.sendPort;
handle = realmCore.createScheduler(Isolate.current.hashCode, sendPort.nativePort);
}

void _handle(dynamic message) {
if (message is List) {
// currently the only `message as List` is from the logger.
final category = LogCategory.fromString(message[0] as String);
final level = LogLevel.values[message[1] as int];
final text = message[2] as String;
Realm.logger.raise((category: category, level: level, message: text));
} else if (message is int) {
realmCore.invokeScheduler(message);
} else {
Realm.logger.log(LogLevel.error, 'Unexpected Scheduler message type: ${message.runtimeType} - $message');
}
}

void stop() {
if (handle.released) {
return;
Expand Down
Loading