mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
8b2cacf9ca
Remove SDK copies of `arena.dart` which is now in `package:ffi`. Change-Id: Ic4808c473043be7d34cd1334406897a935c19263 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/204020 Auto-Submit: Nate Bosch <nbosch@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com>
89 lines
2.9 KiB
Dart
89 lines
2.9 KiB
Dart
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
//
|
|
// Sample illustrating resources are not cleaned up when isolate is shutdown.
|
|
|
|
import 'dart:io';
|
|
import "dart:isolate";
|
|
import 'dart:ffi';
|
|
|
|
import 'package:expect/expect.dart';
|
|
import 'package:ffi/ffi.dart';
|
|
|
|
import '../dylib_utils.dart';
|
|
|
|
void main() {
|
|
final receiveFromHelper = ReceivePort();
|
|
|
|
Isolate.spawn(helperIsolateMain, receiveFromHelper.sendPort)
|
|
.then((helperIsolate) {
|
|
helperIsolate.addOnExitListener(
|
|
receiveFromHelper.sendPort,
|
|
);
|
|
print("Main: Helper started.");
|
|
Pointer<SomeResource> resource = nullptr;
|
|
receiveFromHelper.listen((message) {
|
|
if (message is int) {
|
|
resource = Pointer<SomeResource>.fromAddress(message);
|
|
print("Main: Received resource from helper: $resource.");
|
|
print("Main: Shutting down helper.");
|
|
helperIsolate.kill(priority: Isolate.immediate);
|
|
} else {
|
|
// Isolate kill message.
|
|
Expect.isNull(message);
|
|
print("Main: Helper is shut down.");
|
|
print(
|
|
"Main: Trying to use resource after isolate that was supposed to free it was shut down.");
|
|
useResource(resource);
|
|
print("Main: Releasing resource manually.");
|
|
releaseResource(resource);
|
|
print("Main: Shutting down receive port, end of main.");
|
|
receiveFromHelper.close();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/// If set to `false`, this sample can segfault due to use after free and
|
|
/// double free.
|
|
const keepHelperIsolateAlive = true;
|
|
|
|
void helperIsolateMain(SendPort sendToMain) {
|
|
using((Arena arena) {
|
|
final resource = arena.using(allocateResource(), releaseResource);
|
|
arena.onReleaseAll(() {
|
|
// Will only run print if [keepHelperIsolateAlive] is false.
|
|
print("Helper: Releasing all resources.");
|
|
});
|
|
print("Helper: Resource allocated.");
|
|
useResource(resource);
|
|
print("Helper: Sending resource to main: $resource.");
|
|
sendToMain.send(resource.address);
|
|
print("Helper: Going to sleep.");
|
|
if (keepHelperIsolateAlive) {
|
|
while (true) {
|
|
sleep(Duration(seconds: 1));
|
|
print("Helper: sleeping.");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
final ffiTestDynamicLibrary =
|
|
dlopenPlatformSpecific("ffi_test_dynamic_library");
|
|
|
|
final allocateResource = ffiTestDynamicLibrary.lookupFunction<
|
|
Pointer<SomeResource> Function(),
|
|
Pointer<SomeResource> Function()>("AllocateResource");
|
|
|
|
final useResource = ffiTestDynamicLibrary.lookupFunction<
|
|
Void Function(Pointer<SomeResource>),
|
|
void Function(Pointer<SomeResource>)>("UseResource");
|
|
|
|
final releaseResource = ffiTestDynamicLibrary.lookupFunction<
|
|
Void Function(Pointer<SomeResource>),
|
|
void Function(Pointer<SomeResource>)>("ReleaseResource");
|
|
|
|
/// Represents some opaque resource being managed by a library.
|
|
class SomeResource extends Opaque {}
|