e2efffa005
This reland commit5a32d8bc7cwith a fix for thread leak (Issue #56717): when `ThreadPool` is shutting down asynchronously the last worker should detach itself to prevent leaking associated low-level data structures, because no thread will join it. A hang in service isolate shutdown (caused by an existing bug) was fixed by commit157a0dc7f9. This CL turns native ports into a thin abstraction over underlying thread pool instead of building them as full fledged MessageHandler. This allows to easily implement a variation of native ports which can handle messages concurrently with the given degree of concurrency. This type of port can be used to greatly simplify implementation of IOService - which previously had to do its own concurrency management on top of "single threaded" native ports. This capability is exposed as `Dart_NewConcurrentNativePort` API. The new implementation is in general much cleaner then the old one with one exception: `Dart_CloseNativePort` API has unfortunate design where underlying message handler is destroyed asynchronously and `Dart_CloseNativePort` returns immediately without waiting for pending tasks to complete. Implementing this on top of `ThreadPool` requires some changes to thread pool implementation. Issue https://github.com/dart-lang/sdk/issues/55844 Closes https://github.com/dart-lang/sdk/issues/56717 TEST=ci Change-Id: Ic68bfb60757685afd75c80a70cdec66cc13c149b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/385000 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Slava Egorov <vegorov@google.com>
370 lines
10 KiB
Dart
370 lines
10 KiB
Dart
// Copyright (c) 2023, 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.
|
|
|
|
import "dart:io";
|
|
import "package:expect/expect.dart";
|
|
|
|
import "use_flag_test_helper.dart";
|
|
|
|
main() {
|
|
if (Platform.isWindows) return;
|
|
if (Platform.isAndroid) return; // no nm available on test device
|
|
|
|
var nm;
|
|
for (var path in [
|
|
if (Platform.isLinux) ...[
|
|
"buildtools/linux-arm64/clang/bin/llvm-nm",
|
|
"buildtools/linux-x64/clang/bin/llvm-nm",
|
|
],
|
|
if (Platform.isMacOS) ...[
|
|
"buildtools/mac-arm64/clang/bin/llvm-nm",
|
|
"buildtools/mac-x64/clang/bin/llvm-nm",
|
|
],
|
|
]) {
|
|
if (new File(path).existsSync()) {
|
|
nm = path;
|
|
break;
|
|
}
|
|
}
|
|
if (nm == null) {
|
|
throw "Could not find nm";
|
|
}
|
|
|
|
var result = Process.runSync(nm, [
|
|
Platform.isMacOS ? "--extern-only" : "--dynamic",
|
|
"--defined-only",
|
|
"--format=just-symbols",
|
|
Platform.executable
|
|
]);
|
|
if (result.exitCode != 0) {
|
|
print("nm failed");
|
|
print(result.stdout);
|
|
print(result.stderr);
|
|
throw "nm failed";
|
|
}
|
|
|
|
var symbols = result.stdout.split("\n")..remove("");
|
|
if (Platform.isMacOS) {
|
|
// Remove leading underscores.
|
|
for (var i = 0; i < symbols.length; i++) {
|
|
symbols[i] = symbols[i].substring(1);
|
|
}
|
|
}
|
|
symbols.remove("_IO_stdin_used"); // Only on IA32 for libc.
|
|
print(symbols);
|
|
|
|
var expectedSymbols = [
|
|
"Dart_AddSymbols",
|
|
"Dart_Allocate",
|
|
"Dart_AllocateWithNativeFields",
|
|
"Dart_BooleanValue",
|
|
"Dart_ClassLibrary",
|
|
"Dart_ClassName",
|
|
"Dart_Cleanup",
|
|
"Dart_CloseNativePort",
|
|
"Dart_ClosureFunction",
|
|
"Dart_CompileAll",
|
|
"Dart_CompileToKernel",
|
|
"Dart_CopyUTF8EncodingOfString",
|
|
"Dart_CreateAppAOTSnapshotAsAssemblies",
|
|
"Dart_CreateAppAOTSnapshotAsAssembly",
|
|
"Dart_CreateAppAOTSnapshotAsElf",
|
|
"Dart_CreateAppAOTSnapshotAsElfs",
|
|
"Dart_CreateAppJITSnapshotAsBlobs",
|
|
"Dart_CreateIsolateGroup",
|
|
"Dart_CreateIsolateGroupFromKernel",
|
|
"Dart_CreateIsolateInGroup",
|
|
"Dart_CreateSnapshot",
|
|
"Dart_CreateVMAOTSnapshotAsAssembly",
|
|
"Dart_CurrentIsolate",
|
|
"Dart_CurrentIsolateData",
|
|
"Dart_CurrentIsolateGroup",
|
|
"Dart_CurrentIsolateGroupData",
|
|
"Dart_CurrentIsolateGroupId",
|
|
"Dart_DebugName",
|
|
"Dart_DebugNameToCString",
|
|
"Dart_DeferredLoadComplete",
|
|
"Dart_DeferredLoadCompleteError",
|
|
"Dart_DeleteFinalizableHandle",
|
|
"Dart_DeletePersistentHandle",
|
|
"Dart_DeleteWeakPersistentHandle",
|
|
"Dart_DetectNullSafety",
|
|
"Dart_DisableHeapSampling",
|
|
"Dart_DoubleValue",
|
|
"Dart_DumpNativeStackTrace",
|
|
"Dart_EmptyString",
|
|
"Dart_EnableHeapSampling",
|
|
"Dart_EnterIsolate",
|
|
"Dart_EnterScope",
|
|
"Dart_ErrorGetException",
|
|
"Dart_ErrorGetStackTrace",
|
|
"Dart_ErrorHasException",
|
|
"Dart_ExecuteInternalCommand",
|
|
"Dart_ExitIsolate",
|
|
"Dart_ExitScope",
|
|
"Dart_False",
|
|
"Dart_FinalizeAllClasses",
|
|
"Dart_FinalizeLoading",
|
|
"Dart_FunctionIsStatic",
|
|
"Dart_FunctionName",
|
|
"Dart_FunctionOwner",
|
|
"Dart_GetClass",
|
|
"Dart_GetCurrentUserTag",
|
|
"Dart_GetDataFromByteBuffer",
|
|
"Dart_GetDefaultUserTag",
|
|
"Dart_GetError",
|
|
"Dart_GetField",
|
|
"Dart_GetLoadedLibraries",
|
|
"Dart_GetMainPortId",
|
|
"Dart_GetMessageNotifyCallback",
|
|
"Dart_GetNativeArgument",
|
|
"Dart_GetNativeArgumentCount",
|
|
"Dart_GetNativeArguments",
|
|
"Dart_GetNativeBooleanArgument",
|
|
"Dart_GetNativeDoubleArgument",
|
|
"Dart_GetNativeFieldsOfArgument",
|
|
"Dart_GetNativeInstanceField",
|
|
"Dart_GetNativeInstanceFieldCount",
|
|
"Dart_GetNativeIntegerArgument",
|
|
"Dart_GetNativeIsolateGroupData",
|
|
"Dart_GetNativeReceiver",
|
|
"Dart_GetNativeResolver",
|
|
"Dart_GetNativeStringArgument",
|
|
"Dart_GetNativeSymbol",
|
|
"Dart_GetNonNullableType",
|
|
"Dart_GetNullableType",
|
|
"Dart_GetObfuscationMap",
|
|
"Dart_GetPeer",
|
|
"Dart_GetStaticMethodClosure",
|
|
"Dart_GetStickyError",
|
|
"Dart_GetType",
|
|
"Dart_GetTypeOfExternalTypedData",
|
|
"Dart_GetTypeOfTypedData",
|
|
"Dart_GetUserTagLabel",
|
|
"Dart_HandleFromPersistent",
|
|
"Dart_HandleFromWeakPersistent",
|
|
"Dart_HandleMessage",
|
|
"Dart_HandleServiceMessages",
|
|
"Dart_HasLivePorts",
|
|
"Dart_HasServiceMessages",
|
|
"Dart_HasStickyError",
|
|
"Dart_IdentityEquals",
|
|
"Dart_Initialize",
|
|
"Dart_InitializeNativeAssetsResolver",
|
|
"Dart_InstanceGetType",
|
|
"Dart_IntegerFitsIntoInt64",
|
|
"Dart_IntegerFitsIntoUint64",
|
|
"Dart_IntegerToHexCString",
|
|
"Dart_IntegerToInt64",
|
|
"Dart_IntegerToUint64",
|
|
"Dart_Invoke",
|
|
"Dart_InvokeClosure",
|
|
"Dart_InvokeConstructor",
|
|
"Dart_InvokeVMServiceMethod",
|
|
"Dart_IsApiError",
|
|
"Dart_IsBoolean",
|
|
"Dart_IsByteBuffer",
|
|
"Dart_IsClosure",
|
|
"Dart_IsCompilationError",
|
|
"Dart_IsDouble",
|
|
"Dart_IsError",
|
|
"Dart_IsFatalError",
|
|
"Dart_IsFunction",
|
|
"Dart_IsFuture",
|
|
"Dart_IsInstance",
|
|
"Dart_IsInteger",
|
|
"Dart_IsKernel",
|
|
"Dart_IsKernelIsolate",
|
|
"Dart_IsLibrary",
|
|
"Dart_IsList",
|
|
"Dart_IsMap",
|
|
"Dart_IsNonNullableType",
|
|
"Dart_IsNull",
|
|
"Dart_IsNullableType",
|
|
"Dart_IsNumber",
|
|
"Dart_IsolateData",
|
|
"Dart_IsolateFlagsInitialize",
|
|
"Dart_IsolateGroupData",
|
|
"Dart_IsolateGroupHeapNewCapacityMetric",
|
|
"Dart_IsolateGroupHeapNewExternalMetric",
|
|
"Dart_IsolateGroupHeapNewUsedMetric",
|
|
"Dart_IsolateGroupHeapOldCapacityMetric",
|
|
"Dart_IsolateGroupHeapOldExternalMetric",
|
|
"Dart_IsolateGroupHeapOldUsedMetric",
|
|
"Dart_IsolateMakeRunnable",
|
|
"Dart_IsolateRunnableHeapSizeMetric",
|
|
"Dart_IsolateRunnableLatencyMetric",
|
|
"Dart_IsolateServiceId",
|
|
"Dart_IsPausedOnExit",
|
|
"Dart_IsPausedOnStart",
|
|
"Dart_IsPrecompiledRuntime",
|
|
"Dart_IsReloading",
|
|
"Dart_IsServiceIsolate",
|
|
"Dart_IsString",
|
|
"Dart_IsStringLatin1",
|
|
"Dart_IsTearOff",
|
|
"Dart_IsType",
|
|
"Dart_IsTypedData",
|
|
"Dart_IsTypeVariable",
|
|
"Dart_IsUnhandledExceptionError",
|
|
"Dart_IsVariable",
|
|
"Dart_IsVMFlagSet",
|
|
"Dart_KernelIsolateIsRunning",
|
|
"Dart_KernelListDependencies",
|
|
"Dart_KernelPort",
|
|
"Dart_KillIsolate",
|
|
"Dart_LibraryHandleError",
|
|
"Dart_LibraryResolvedUrl",
|
|
"Dart_LibraryUrl",
|
|
"Dart_ListGetAsBytes",
|
|
"Dart_ListGetAt",
|
|
"Dart_ListGetRange",
|
|
"Dart_ListLength",
|
|
"Dart_ListSetAsBytes",
|
|
"Dart_ListSetAt",
|
|
"Dart_LoadingUnitLibraryUris",
|
|
"Dart_LoadLibrary",
|
|
"Dart_LoadLibraryFromKernel",
|
|
"Dart_LoadScriptFromKernel",
|
|
"Dart_LookupLibrary",
|
|
"Dart_MapContainsKey",
|
|
"Dart_MapGetAt",
|
|
"Dart_MapKeys",
|
|
"Dart_New",
|
|
"Dart_NewApiError",
|
|
"Dart_NewBoolean",
|
|
"Dart_NewByteBuffer",
|
|
"Dart_NewCompilationError",
|
|
"Dart_NewDouble",
|
|
"Dart_NewExternalTypedData",
|
|
"Dart_NewExternalTypedDataWithFinalizer",
|
|
"Dart_NewFinalizableHandle",
|
|
"Dart_NewInteger",
|
|
"Dart_NewIntegerFromHexCString",
|
|
"Dart_NewIntegerFromUint64",
|
|
"Dart_NewList",
|
|
"Dart_NewListOfType",
|
|
"Dart_NewListOfTypeFilled",
|
|
"Dart_NewNativePort",
|
|
"Dart_NewConcurrentNativePort",
|
|
"Dart_NewPersistentHandle",
|
|
"Dart_NewSendPort",
|
|
"Dart_NewSendPortEx",
|
|
"Dart_NewStringFromCString",
|
|
"Dart_NewStringFromUTF16",
|
|
"Dart_NewStringFromUTF32",
|
|
"Dart_NewStringFromUTF8",
|
|
"Dart_NewTypedData",
|
|
"Dart_NewUnhandledExceptionError",
|
|
"Dart_NewUnmodifiableExternalTypedDataWithFinalizer",
|
|
"Dart_NewUserTag",
|
|
"Dart_NewWeakPersistentHandle",
|
|
"Dart_NotifyDestroyed",
|
|
"Dart_NotifyIdle",
|
|
"Dart_NotifyLowMemory",
|
|
"Dart_Null",
|
|
"Dart_ObjectEquals",
|
|
"Dart_ObjectIsType",
|
|
"Dart_Post",
|
|
"Dart_PostCObject",
|
|
"Dart_PostInteger",
|
|
"Dart_Precompile",
|
|
"Dart_PrepareToAbort",
|
|
"Dart_PropagateError",
|
|
"Dart_RecordTimelineEvent",
|
|
"Dart_RegisterHeapSamplingCallback",
|
|
"Dart_RegisterIsolateServiceRequestCallback",
|
|
"Dart_RegisterRootServiceRequestCallback",
|
|
"Dart_ReportSurvivingAllocations",
|
|
"Dart_ReThrowException",
|
|
"Dart_RootLibrary",
|
|
"Dart_RunLoop",
|
|
"Dart_RunLoopAsync",
|
|
"Dart_ScopeAllocate",
|
|
"Dart_SendPortGetId",
|
|
"Dart_SendPortGetIdEx",
|
|
"Dart_ServiceSendDataEvent",
|
|
"Dart_SetBooleanReturnValue",
|
|
"Dart_SetCurrentUserTag",
|
|
"Dart_SetDartLibrarySourcesKernel",
|
|
"Dart_SetDeferredLoadHandler",
|
|
"Dart_SetDoubleReturnValue",
|
|
"Dart_SetDwarfStackTraceFootnoteCallback",
|
|
"Dart_SetEmbedderInformationCallback",
|
|
"Dart_SetEnabledTimelineCategory",
|
|
"Dart_SetEnvironmentCallback",
|
|
"Dart_SetFfiNativeResolver",
|
|
"Dart_SetField",
|
|
"Dart_SetFileModifiedCallback",
|
|
"Dart_SetHeapSamplingPeriod",
|
|
"Dart_SetIntegerReturnValue",
|
|
"Dart_SetLibraryTagHandler",
|
|
"Dart_SetMessageNotifyCallback",
|
|
"Dart_SetNativeInstanceField",
|
|
"Dart_SetNativeResolver",
|
|
"Dart_SetPausedOnExit",
|
|
"Dart_SetPausedOnStart",
|
|
"Dart_SetPeer",
|
|
"Dart_SetPerformanceMode",
|
|
"Dart_SetPersistentHandle",
|
|
"Dart_SetReturnValue",
|
|
"Dart_SetRootLibrary",
|
|
"Dart_SetServiceStreamCallbacks",
|
|
"Dart_SetShouldPauseOnExit",
|
|
"Dart_SetShouldPauseOnStart",
|
|
"Dart_SetStickyError",
|
|
"Dart_SetThreadName",
|
|
"Dart_SetTimelineRecorderCallback",
|
|
"Dart_SetVMFlags",
|
|
"Dart_SetWeakHandleReturnValue",
|
|
"Dart_ShouldPauseOnExit",
|
|
"Dart_ShouldPauseOnStart",
|
|
"Dart_ShutdownIsolate",
|
|
"Dart_SortClasses",
|
|
"Dart_StartProfiling",
|
|
"Dart_StopProfiling",
|
|
"Dart_StringGetProperties",
|
|
"Dart_StringLength",
|
|
"Dart_StringStorageSize",
|
|
"Dart_StringToCString",
|
|
"Dart_StringToLatin1",
|
|
"Dart_StringToUTF16",
|
|
"Dart_StringToUTF8",
|
|
"Dart_StringUTF8Length",
|
|
"Dart_ThreadDisableProfiling",
|
|
"Dart_ThreadEnableProfiling",
|
|
"Dart_ThrowException",
|
|
"Dart_TimelineGetMicros",
|
|
"Dart_TimelineGetTicks",
|
|
"Dart_TimelineGetTicksFrequency",
|
|
"Dart_ToString",
|
|
"Dart_True",
|
|
"Dart_TypedDataAcquireData",
|
|
"Dart_TypedDataReleaseData",
|
|
"Dart_TypeDynamic",
|
|
"Dart_TypeNever",
|
|
"Dart_TypeToNonNullableType",
|
|
"Dart_TypeToNullableType",
|
|
"Dart_TypeVoid",
|
|
"Dart_VersionString",
|
|
"Dart_WriteHeapSnapshot",
|
|
"Dart_WriteProfileToTimeline",
|
|
];
|
|
|
|
if (isAOTRuntime) {
|
|
expectedSymbols.addAll([
|
|
"Dart_LoadELF",
|
|
"Dart_LoadELF_Memory",
|
|
"Dart_UnloadELF",
|
|
]);
|
|
if (!Platform.isMacOS) {
|
|
expectedSymbols.addAll([
|
|
"Dart_LoadELF_Fd",
|
|
]);
|
|
}
|
|
}
|
|
|
|
Expect.setEquals(expectedSymbols, symbols);
|
|
}
|