mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
On Fuchsia, we can now get executable VMOs from trusted backing filesystems. This allows us to remove the use of replace_as_executable in favor of opening files with `fdio_open_fd_at` with the `OPEN_RIGHT_EXECUTABLE` flag and getting VMOs by calling `fdio_get_vmo_exec`. By moving the responsibility for executability into the filesystem, we are able to remove `deprecated-ambient-replace-as-executable` from component manifests for non-JIT runners (the JIT runners still call replace_as_executable in Dart's allocator). It wasn't abundantly clear whether .cmx files for tests were used purely in AOT runtime environments or also saw JIT usage, so I left those as-is. For context: this is a second attempt at #16690, which was reverted because it broke the Dart JIT runner. The primary difference is that this time around, we correctly handle absolute vs relative paths, depending on whether library loading bottoms out in `fdio_open_fd` or `fdio_open_fd_at`. I've added additional assertions to help ensure any new usages use the correct shape of path. Testing: I verified locally that the flutter product runner works on Astro, and also successfully ran the Dart JIT example test (which was the thing blocking the google3 roll with the previous attempt at this patchset). Co-authored-by: Drew Fisher <zarvox@google.com>
211 lines
7.3 KiB
C++
211 lines
7.3 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "service_isolate.h"
|
|
|
|
#include "runtime/dart/utils/inlines.h"
|
|
#include "third_party/dart/runtime/include/bin/dart_io_api.h"
|
|
#include "third_party/tonic/converter/dart_converter.h"
|
|
#include "third_party/tonic/dart_library_natives.h"
|
|
#include "third_party/tonic/dart_microtask_queue.h"
|
|
#include "third_party/tonic/dart_state.h"
|
|
#include "third_party/tonic/typed_data/typed_list.h"
|
|
|
|
#include "builtin_libraries.h"
|
|
#include "dart_component_controller.h"
|
|
#include "logging.h"
|
|
|
|
namespace dart_runner {
|
|
namespace {
|
|
|
|
dart_utils::ElfSnapshot elf_snapshot; // AOT snapshot
|
|
dart_utils::MappedResource mapped_isolate_snapshot_data; // JIT snapshot
|
|
dart_utils::MappedResource
|
|
mapped_isolate_snapshot_instructions; // JIT snapshot
|
|
tonic::DartLibraryNatives* service_natives = nullptr;
|
|
|
|
Dart_NativeFunction GetNativeFunction(Dart_Handle name,
|
|
int argument_count,
|
|
bool* auto_setup_scope) {
|
|
dart_utils::Check(service_natives, LOG_TAG);
|
|
return service_natives->GetNativeFunction(name, argument_count,
|
|
auto_setup_scope);
|
|
}
|
|
|
|
const uint8_t* GetSymbol(Dart_NativeFunction native_function) {
|
|
dart_utils::Check(service_natives, LOG_TAG);
|
|
return service_natives->GetSymbol(native_function);
|
|
}
|
|
|
|
#define SHUTDOWN_ON_ERROR(handle) \
|
|
if (Dart_IsError(handle)) { \
|
|
*error = strdup(Dart_GetError(handle)); \
|
|
FX_LOG(ERROR, LOG_TAG, *error); \
|
|
Dart_ExitScope(); \
|
|
Dart_ShutdownIsolate(); \
|
|
return nullptr; \
|
|
}
|
|
|
|
void NotifyServerState(Dart_NativeArguments args) {
|
|
// NOP.
|
|
}
|
|
|
|
void Shutdown(Dart_NativeArguments args) {
|
|
// NOP.
|
|
}
|
|
|
|
void EmbedderInformationCallback(Dart_EmbedderInformation* info) {
|
|
info->version = DART_EMBEDDER_INFORMATION_CURRENT_VERSION;
|
|
info->name = "dart_runner";
|
|
info->current_rss = -1;
|
|
info->max_rss = -1;
|
|
|
|
zx_info_task_stats_t task_stats;
|
|
zx_handle_t process = zx_process_self();
|
|
zx_status_t status = zx_object_get_info(
|
|
process, ZX_INFO_TASK_STATS, &task_stats, sizeof(task_stats), NULL, NULL);
|
|
if (status == ZX_OK) {
|
|
info->current_rss =
|
|
task_stats.mem_private_bytes + task_stats.mem_shared_bytes;
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
Dart_Isolate CreateServiceIsolate(const char* uri,
|
|
Dart_IsolateFlags* flags,
|
|
char** error) {
|
|
Dart_SetEmbedderInformationCallback(EmbedderInformationCallback);
|
|
|
|
const uint8_t *vmservice_data = nullptr, *vmservice_instructions = nullptr;
|
|
|
|
#if defined(AOT_RUNTIME)
|
|
// The VM service was compiled as a separate app.
|
|
const char* snapshot_path = "/pkg/data/vmservice_snapshot.so";
|
|
if (elf_snapshot.Load(nullptr, snapshot_path)) {
|
|
vmservice_data = elf_snapshot.IsolateData();
|
|
vmservice_instructions = elf_snapshot.IsolateInstrs();
|
|
if (vmservice_data == nullptr || vmservice_instructions == nullptr) {
|
|
return nullptr;
|
|
}
|
|
} else {
|
|
// The VM service was compiled as a separate app.
|
|
const char* snapshot_data_path =
|
|
"/pkg/data/vmservice_isolate_snapshot_data.bin";
|
|
const char* snapshot_instructions_path =
|
|
"/pkg/data/vmservice_isolate_snapshot_instructions.bin";
|
|
#else
|
|
// The VM service is embedded in the core snapshot.
|
|
const char* snapshot_data_path = "/pkg/data/isolate_core_snapshot_data.bin";
|
|
const char* snapshot_instructions_path =
|
|
"/pkg/data/isolate_core_snapshot_instructions.bin";
|
|
#endif
|
|
|
|
if (!dart_utils::MappedResource::LoadFromNamespace(
|
|
nullptr, snapshot_data_path, mapped_isolate_snapshot_data)) {
|
|
*error = strdup("Failed to load snapshot for service isolate");
|
|
FX_LOG(ERROR, LOG_TAG, *error);
|
|
return nullptr;
|
|
}
|
|
if (!dart_utils::MappedResource::LoadFromNamespace(
|
|
nullptr, snapshot_instructions_path,
|
|
mapped_isolate_snapshot_instructions, true /* executable */)) {
|
|
*error = strdup("Failed to load snapshot for service isolate");
|
|
FX_LOG(ERROR, LOG_TAG, *error);
|
|
return nullptr;
|
|
}
|
|
|
|
vmservice_data = mapped_isolate_snapshot_data.address();
|
|
vmservice_instructions = mapped_isolate_snapshot_instructions.address();
|
|
#if defined(AOT_RUNTIME)
|
|
}
|
|
#endif
|
|
|
|
auto state = new std::shared_ptr<tonic::DartState>(new tonic::DartState());
|
|
Dart_Isolate isolate = Dart_CreateIsolateGroup(
|
|
uri, DART_VM_SERVICE_ISOLATE_NAME, vmservice_data, vmservice_instructions,
|
|
nullptr /* flags */, state, state, error);
|
|
if (!isolate) {
|
|
FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolateGroup failed: %s", *error);
|
|
return nullptr;
|
|
}
|
|
|
|
state->get()->SetIsolate(isolate);
|
|
|
|
// Setup native entries.
|
|
service_natives = new tonic::DartLibraryNatives();
|
|
service_natives->Register({
|
|
{"VMServiceIO_NotifyServerState", NotifyServerState, 1, true},
|
|
{"VMServiceIO_Shutdown", Shutdown, 0, true},
|
|
});
|
|
|
|
Dart_EnterScope();
|
|
|
|
Dart_Handle library =
|
|
Dart_LookupLibrary(Dart_NewStringFromCString("dart:vmservice_io"));
|
|
SHUTDOWN_ON_ERROR(library);
|
|
Dart_Handle result = Dart_SetRootLibrary(library);
|
|
SHUTDOWN_ON_ERROR(result);
|
|
result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol);
|
|
SHUTDOWN_ON_ERROR(result);
|
|
|
|
// _ip = '127.0.0.1'
|
|
result = Dart_SetField(library, Dart_NewStringFromCString("_ip"),
|
|
Dart_NewStringFromCString("127.0.0.1"));
|
|
SHUTDOWN_ON_ERROR(result);
|
|
|
|
// _port = 0
|
|
result = Dart_SetField(library, Dart_NewStringFromCString("_port"),
|
|
Dart_NewInteger(0));
|
|
SHUTDOWN_ON_ERROR(result);
|
|
|
|
// _autoStart = true
|
|
result = Dart_SetField(library, Dart_NewStringFromCString("_autoStart"),
|
|
Dart_NewBoolean(true));
|
|
SHUTDOWN_ON_ERROR(result);
|
|
|
|
// _originCheckDisabled = false
|
|
result =
|
|
Dart_SetField(library, Dart_NewStringFromCString("_originCheckDisabled"),
|
|
Dart_NewBoolean(false));
|
|
SHUTDOWN_ON_ERROR(result);
|
|
|
|
// _authCodesDisabled = false
|
|
result =
|
|
Dart_SetField(library, Dart_NewStringFromCString("_authCodesDisabled"),
|
|
Dart_NewBoolean(false));
|
|
SHUTDOWN_ON_ERROR(result);
|
|
|
|
InitBuiltinLibrariesForIsolate(std::string(uri), nullptr, fileno(stdout),
|
|
fileno(stderr), nullptr, zx::channel(), true);
|
|
|
|
// Make runnable.
|
|
Dart_ExitScope();
|
|
Dart_ExitIsolate();
|
|
*error = Dart_IsolateMakeRunnable(isolate);
|
|
if (*error != nullptr) {
|
|
FX_LOG(ERROR, LOG_TAG, *error);
|
|
Dart_EnterIsolate(isolate);
|
|
Dart_ShutdownIsolate();
|
|
return nullptr;
|
|
}
|
|
return isolate;
|
|
} // namespace dart_runner
|
|
|
|
Dart_Handle GetVMServiceAssetsArchiveCallback() {
|
|
dart_utils::MappedResource observatory_tar;
|
|
if (!dart_utils::MappedResource::LoadFromNamespace(
|
|
nullptr, "/pkg/data/observatory.tar", observatory_tar)) {
|
|
FX_LOG(ERROR, LOG_TAG, "Failed to load Observatory assets");
|
|
return nullptr;
|
|
}
|
|
// TODO(rmacnak): Should we avoid copying the tar? Or does the service
|
|
// library not hold onto it anyway?
|
|
return tonic::DartConverter<tonic::Uint8List>::ToDart(
|
|
reinterpret_cast<const uint8_t*>(observatory_tar.address()),
|
|
observatory_tar.size());
|
|
}
|
|
|
|
} // namespace dart_runner
|