Files
sdk/samples/ffi/resource_management/pool_isolate_shutdown_sample.dart
T
Daco Harkes 5d40d52fca [vm/ffi] Add Opaque type
Issue: https://github.com/dart-lang/sdk/issues/44622
Issue: https://github.com/dart-lang/sdk/issues/43974

TEST=samples/ffi/sqlite/lib/src/bindings/types.dart
TEST=tests/ffi/vmspecific_static_checks_test.dart

Change-Id: Ib9e72df6a07b1bc2b72a7db66f945652814baf51
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,analyzer-nnbd-linux-release-try,front-end-linux-release-x64-try,front-end-nnbd-linux-release-x64-try,benchmark-linux-try,dart-sdk-linux-try,pkg-linux-release-try,vm-ffi-android-release-arm-try,vm-ffi-android-release-arm64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-win-debug-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/178984
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Clement Skau <cskau@google.com>
2021-01-13 17:04:08 +00:00

90 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 'pool.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((Pool pool) {
final resource = pool.using(allocateResource(), releaseResource);
pool.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 {}