Skip to content

Commit 6f28908

Browse files
committed
fix: Fix spawning isolates
Setup the IO library, which needs to be setup to have Isolate.spawn work as it initializes the `VMService.script` callback (through `_Platform._nativeScript`). Call `SetupCoreLibraries` from `OnIsolateInitialize` so that async functions in Isolates work Add an example / test for isolate spawning.
1 parent 19d33df commit 6f28908

File tree

8 files changed

+189
-12
lines changed

8 files changed

+189
-12
lines changed

Diff for: examples/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
cmake_minimum_required(VERSION 3.21)
22

3+
add_subdirectory(isolate_spawn)
34
add_subdirectory(simple_example)
45
add_subdirectory(simple_example_ffi)
56
add_subdirectory(realtime_example)

Diff for: examples/isolate_spawn/CMakeLists.txt

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
cmake_minimum_required(VERSION 3.21)
2+
3+
project(isolate_spawn)
4+
5+
add_executable(isolate_spawn main.cpp)
6+
7+
target_include_directories(isolate_spawn PRIVATE
8+
"${DART_DLL_DIR}"
9+
"${DART_DIR}/runtime/include"
10+
)
11+
12+
if(WIN32)
13+
add_custom_command(TARGET isolate_spawn POST_BUILD
14+
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:isolate_spawn> $<TARGET_FILE_DIR:isolate_spawn>
15+
COMMAND_EXPAND_LISTS
16+
)
17+
endif()
18+
19+
add_custom_command(TARGET isolate_spawn POST_BUILD
20+
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/hello_world.dart $<TARGET_FILE_DIR:isolate_spawn>
21+
COMMAND_EXPAND_LISTS
22+
)
23+
24+
target_link_libraries(isolate_spawn PUBLIC dart_dll)
25+
26+
if (MSVC)
27+
set_property(TARGET isolate_spawn PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $<TARGET_FILE_DIR:isolate_spawn>)
28+
endif()

Diff for: examples/isolate_spawn/hello_world.dart

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import 'dart:isolate';
2+
3+
@pragma('vm:external-name', 'SimplePrint')
4+
external void simplePrint(String s);
5+
6+
Future<String> _isolateWorker() async {
7+
simplePrint("Isolate work 1...");
8+
await Future.delayed(Duration(seconds: 10));
9+
simplePrint("Isolate work 2...");
10+
return "done";
11+
}
12+
13+
void main() async {
14+
simplePrint("Hello From Dart!\n");
15+
final isolateValue = await Isolate.run(_isolateWorker);
16+
simplePrint("Isolate complete, returned $isolateValue");
17+
}

Diff for: examples/isolate_spawn/main.cpp

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#include <string.h>
2+
#include <iostream>
3+
4+
#include "dart_dll.h"
5+
6+
#include <dart_api.h>
7+
8+
Dart_Handle HandleError(Dart_Handle handle) {
9+
if (Dart_IsError(handle)) {
10+
Dart_PropagateError(handle);
11+
}
12+
return handle;
13+
}
14+
15+
void SimplePrint(Dart_NativeArguments arguments) {
16+
Dart_Handle string = HandleError(Dart_GetNativeArgument(arguments, 0));
17+
if (Dart_IsString(string)) {
18+
const char* cstring;
19+
Dart_StringToCString(string, &cstring);
20+
std::cout << "Hello from C++. Dart says:\n";
21+
std::cout << cstring << std::endl;
22+
}
23+
}
24+
25+
Dart_NativeFunction ResolveNativeFunction(Dart_Handle name,
26+
int /* argc */,
27+
bool* /* auto_setup_scope */) {
28+
if (!Dart_IsString(name)) {
29+
return nullptr;
30+
}
31+
32+
Dart_NativeFunction result = nullptr;
33+
34+
const char* cname;
35+
HandleError(Dart_StringToCString(name, &cname));
36+
37+
if (strcmp("SimplePrint", cname) == 0) {
38+
result = SimplePrint;
39+
}
40+
41+
return result;
42+
}
43+
44+
int main() {
45+
// Initialize Dart
46+
DartDllConfig config;
47+
config.service_port = 6222;
48+
49+
if (!DartDll_Initialize(config)) {
50+
return -1;
51+
}
52+
53+
// Load your main isolate file, also providing the path to a package config if one exists.
54+
// The build makes sure these are coppied to the output directory for running the example
55+
Dart_Isolate isolate = DartDll_LoadScript("hello_world.dart", nullptr);
56+
if (isolate == nullptr) {
57+
return -1;
58+
}
59+
60+
// With the library loaded, you can now use the dart_api.h functions
61+
// This includes setting the native function resolver:
62+
Dart_EnterIsolate(isolate);
63+
Dart_EnterScope();
64+
65+
Dart_Handle library = Dart_RootLibrary();
66+
Dart_SetNativeResolver(library, ResolveNativeFunction, nullptr);
67+
68+
// And run "main"
69+
Dart_Handle result = DartDll_RunMain(library);
70+
if (Dart_IsError(result)) {
71+
std::cerr << "Failed to invoke main: " << Dart_GetError(result);
72+
}
73+
74+
Dart_ExitScope();
75+
Dart_ShutdownIsolate();
76+
77+
// Don't forget to shutdown
78+
DartDll_Shutdown();
79+
80+
return 0;
81+
}

Diff for: src/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ elseif(APPLE)
100100
endif()
101101

102102
if(LIB_DART_DEBUG)
103-
target_link_libraries(dart_dll debug ${LIB_DART_DEBUG})
103+
target_link_libraries(dart_dll debug ${LIB_DART_DEBUG})
104104
else()
105105
target_link_libraries(dart_dll debug ${LIB_DART_RELEASE})
106106
endif()

Diff for: src/dart_dll.cpp

+34-5
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
#include <bin/dartutils.h>
1010
#include <bin/dfe.h>
1111
#include <bin/gzip.h>
12+
#include <bin/loader.h>
1213
#include <bin/isolate_data.h>
14+
#include <platform/utils.h>
1315

1416
using namespace dart::bin;
17+
using namespace dart;
1518

1619
static DartDllConfig _dart_dll_config;
1720

@@ -74,13 +77,39 @@ bool OnIsolateInitialize(void** child_callback_data, char** error) {
7477
*child_callback_data = isolate_data;
7578

7679
Dart_EnterScope();
80+
81+
const auto script_uri = isolate_group_data->script_url;
82+
// TODO
83+
/*const bool isolate_run_app_snapshot =
84+
isolate_group_data->RunFromAppSnapshot();*/
85+
Dart_Handle result = SetupCoreLibraries(isolate, isolate_data,
86+
/*group_start=*/false,
87+
/*resolved_packages_config=*/nullptr);
88+
if (Dart_IsError(result)) goto failed;
89+
90+
result = DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
91+
if (Dart_IsError(result)) goto failed;
92+
93+
if (isolate_group_data->kernel_buffer() != nullptr) {
94+
// Various core-library parts will send requests to the Loader to resolve
95+
// relative URIs and perform other related tasks. We need Loader to be
96+
// initialized for this to work because loading from Kernel binary
97+
// bypasses normal source code loading paths that initialize it.
98+
const char* resolved_script_uri = nullptr;
99+
result = Dart_StringToCString(result, &resolved_script_uri);
100+
if (Dart_IsError(result)) goto failed;
101+
result = Loader::InitForSnapshot(resolved_script_uri, isolate_data);
102+
if (Dart_IsError(result)) goto failed;
103+
}
104+
105+
Dart_ExitScope();
106+
107+
return true;
77108

78-
// Make the isolate runnable so that it is ready to handle messages.
109+
failed:
110+
*error = Utils::StrDup(Dart_GetError(result));
79111
Dart_ExitScope();
80-
Dart_ExitIsolate();
81-
*error = Dart_IsolateMakeRunnable(isolate);
82-
Dart_EnterIsolate(isolate);
83-
return *error == nullptr;
112+
return false;
84113
}
85114

86115
static void OnIsolateShutdown(void*, void*) {

Diff for: src/isolate_setup.cpp

+19-6
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
#include <include/dart_api.h>
66
#include <include/dart_embedder_api.h>
77

8+
#include <bin/builtin.h>
89
#include <bin/dartutils.h>
910
#include <bin/dfe.h>
1011
#include <bin/isolate_data.h>
1112
#include <bin/loader.h>
1213
#include <bin/snapshot_utils.h>
14+
#include <bin/vmservice_impl.h>
1315
#include <platform/utils.h>
1416

1517
using namespace dart::bin;
@@ -39,8 +41,11 @@ class DllIsolateGroupData : public IsolateGroupData {
3941

4042
Dart_Handle SetupCoreLibraries(Dart_Isolate isolate,
4143
IsolateData* isolate_data,
42-
bool is_isolate_group_start,
44+
bool is_isolate_group_start,
4345
const char** resolved_packages_config) {
46+
auto isolate_group_data = isolate_data->isolate_group_data();
47+
const auto packages_file = isolate_data->packages_file();
48+
const auto script_uri = isolate_group_data->script_url;
4449
Dart_Handle result;
4550

4651
// Prepare builtin and other core libraries for use to resolve URIs.
@@ -49,8 +54,7 @@ Dart_Handle SetupCoreLibraries(Dart_Isolate isolate,
4954
result = DartUtils::PrepareForScriptLoading(false, true);
5055
if (Dart_IsError(result)) return result;
5156

52-
// Setup packages config if specified.
53-
const char* packages_file = isolate_data->packages_file();
57+
// Setup packages config if specified.
5458
result = DartUtils::SetupPackageConfig(packages_file);
5559
if (Dart_IsError(result)) return result;
5660

@@ -65,6 +69,15 @@ Dart_Handle SetupCoreLibraries(Dart_Isolate isolate,
6569
}
6670
}
6771

72+
// Setup the native resolver as the snapshot does not carry it.
73+
Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
74+
Builtin::SetNativeResolver(Builtin::kIOLibrary);
75+
Builtin::SetNativeResolver(Builtin::kCLILibrary);
76+
VmService::SetNativeResolver();
77+
78+
result = DartUtils::SetupIOLibrary(nullptr, script_uri, true);
79+
if (Dart_IsError(result)) return result;
80+
6881
return result;
6982
}
7083

@@ -169,7 +182,7 @@ Dart_Isolate CreateIsolate(bool is_main_isolate,
169182
const uint8_t* isolate_snapshot_data = kDartCoreIsolateSnapshotData;
170183
const uint8_t* isolate_snapshot_instructions =
171184
kDartCoreIsolateSnapshotInstructions;
172-
185+
173186
if (!is_main_isolate) {
174187
app_snapshot = Snapshot::TryReadAppSnapshot(script_uri);
175188
if (app_snapshot != nullptr && app_snapshot->IsJITorAOT()) {
@@ -192,8 +205,8 @@ Dart_Isolate CreateIsolate(bool is_main_isolate,
192205

193206
if (kernel_buffer == nullptr && !isolate_run_app_snapshot) {
194207
dfe.ReadScript(script_uri, app_snapshot, &kernel_buffer,
195-
&kernel_buffer_size, /*decode_uri=*/true,
196-
&kernel_buffer_ptr);
208+
&kernel_buffer_size, /*decode_uri=*/true,
209+
&kernel_buffer_ptr);
197210
}
198211

199212
flags->null_safety = true;

Diff for: src/isolate_setup.h

+8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#pragma once
22

33
#include <include/dart_api.h>
4+
#include <bin/isolate_data.h>
5+
6+
using namespace dart::bin;
47

58
Dart_Isolate CreateKernelIsolate(const char* script_uri,
69
const char* main,
@@ -27,6 +30,11 @@ Dart_Isolate CreateIsolate(bool is_main_isolate,
2730
void* isolate_data,
2831
char** error);
2932

33+
Dart_Handle SetupCoreLibraries(Dart_Isolate isolate,
34+
IsolateData* isolate_data,
35+
bool is_isolate_group_start,
36+
const char** resolved_packages_config);
37+
3038
void* GetUserIsolateData(void* isolate_group_data);
3139

3240
void DeleteIsolateData(void* raw_isolate_group_data, void* raw_isolate_data);

0 commit comments

Comments
 (0)