5d40d52fca
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>
90 lines
2.9 KiB
Dart
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 {}
|