Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix OOL def for dart_isolate_runner #16941

Merged
merged 2 commits into from
Mar 4, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions testing/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ source_set("dart") {
testonly = true

sources = [
"dart_isolate_runner.cc",
"dart_isolate_runner.h",
"elf_loader.cc",
"elf_loader.h",
Expand Down
176 changes: 176 additions & 0 deletions testing/dart_isolate_runner.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// 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 "flutter/testing/dart_isolate_runner.h"

namespace flutter {
namespace testing {
AutoIsolateShutdown::AutoIsolateShutdown(std::shared_ptr<DartIsolate> isolate,
fml::RefPtr<fml::TaskRunner> runner)
: isolate_(std::move(isolate)), runner_(std::move(runner)) {}

AutoIsolateShutdown::~AutoIsolateShutdown() {
if (!IsValid()) {
return;
}
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
runner_, [isolate = std::move(isolate_), &latch]() {
if (!isolate->Shutdown()) {
FML_LOG(ERROR) << "Could not shutdown isolate.";
FML_CHECK(false);
}
latch.Signal();
});
latch.Wait();
}

FML_WARN_UNUSED_RESULT
bool AutoIsolateShutdown::RunInIsolateScope(std::function<bool(void)> closure) {
if (!IsValid()) {
return false;
}

bool result = false;
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
runner_, [this, &result, &latch, closure]() {
tonic::DartIsolateScope scope(isolate_->isolate());
tonic::DartApiScope api_scope;
if (closure) {
result = closure();
}
latch.Signal();
});
latch.Wait();
return true;
}

void RunDartCodeInIsolate(DartVMRef& vm_ref,
std::unique_ptr<AutoIsolateShutdown>& result,
const Settings& settings,
const TaskRunners& task_runners,
std::string entrypoint,
const std::vector<std::string>& args,
const std::string& fixtures_path,
fml::WeakPtr<IOManager> io_manager) {
FML_CHECK(task_runners.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

if (!vm_ref) {
return;
}

auto vm_data = vm_ref.GetVMData();

if (!vm_data) {
return;
}

auto weak_isolate = DartIsolate::CreateRootIsolate(
vm_data->GetSettings(), // settings
vm_data->GetIsolateSnapshot(), // isolate snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
io_manager, // io manager
{}, // unref queue
{}, // image decoder
"main.dart", // advisory uri
"main", // advisory entrypoint
nullptr, // flags
settings.isolate_create_callback, // isolate create callback
settings.isolate_shutdown_callback // isolate shutdown callback
);

auto root_isolate = std::make_unique<AutoIsolateShutdown>(
weak_isolate.lock(), task_runners.GetUITaskRunner());

if (!root_isolate->IsValid()) {
FML_LOG(ERROR) << "Could not create isolate.";
return;
}

if (root_isolate->get()->GetPhase() != DartIsolate::Phase::LibrariesSetup) {
FML_LOG(ERROR) << "Created isolate is in unexpected phase.";
return;
}

if (!DartVM::IsRunningPrecompiledCode()) {
auto kernel_file_path =
fml::paths::JoinPaths({fixtures_path, "kernel_blob.bin"});

if (!fml::IsFile(kernel_file_path)) {
FML_LOG(ERROR) << "Could not locate kernel file.";
return;
}

auto kernel_file = fml::OpenFile(kernel_file_path.c_str(), false,
fml::FilePermission::kRead);

if (!kernel_file.is_valid()) {
FML_LOG(ERROR) << "Kernel file descriptor was invalid.";
return;
}

auto kernel_mapping = std::make_unique<fml::FileMapping>(kernel_file);

if (kernel_mapping->GetMapping() == nullptr) {
FML_LOG(ERROR) << "Could not setup kernel mapping.";
return;
}

if (!root_isolate->get()->PrepareForRunningFromKernel(
std::move(kernel_mapping))) {
FML_LOG(ERROR)
<< "Could not prepare to run the isolate from the kernel file.";
return;
}
} else {
if (!root_isolate->get()->PrepareForRunningFromPrecompiledCode()) {
FML_LOG(ERROR)
<< "Could not prepare to run the isolate from precompiled code.";
return;
}
}

if (root_isolate->get()->GetPhase() != DartIsolate::Phase::Ready) {
FML_LOG(ERROR) << "Isolate is in unexpected phase.";
return;
}

if (!root_isolate->get()->Run(entrypoint, args,
settings.root_isolate_create_callback)) {
FML_LOG(ERROR) << "Could not run the method \"" << entrypoint
<< "\" in the isolate.";
return;
}

root_isolate->get()->AddIsolateShutdownCallback(
settings.root_isolate_shutdown_callback);

result = std::move(root_isolate);
}

std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolate(
DartVMRef& vm_ref,
const Settings& settings,
const TaskRunners& task_runners,
std::string entrypoint,
const std::vector<std::string>& args,
const std::string& fixtures_path,
fml::WeakPtr<IOManager> io_manager) {
std::unique_ptr<AutoIsolateShutdown> result;
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetPlatformTaskRunner(), fml::MakeCopyable([&]() mutable {
RunDartCodeInIsolate(vm_ref, result, settings, task_runners, entrypoint,
args, fixtures_path, io_manager);
latch.Signal();
}));
latch.Wait();
return result;
}

} // namespace testing
} // namespace flutter
175 changes: 22 additions & 153 deletions testing/dart_isolate_runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_TESTING_DART_ISOLATE_RUNNER_H_
#define FLUTTER_TESTING_DART_ISOLATE_RUNNER_H_

#include "flutter/common/task_runners.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/thread.h"
#include "flutter/runtime/dart_isolate.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/runtime/dart_vm_lifecycle.h"

namespace flutter {
namespace testing {
Expand All @@ -15,47 +22,14 @@ class AutoIsolateShutdown {
AutoIsolateShutdown() = default;

AutoIsolateShutdown(std::shared_ptr<DartIsolate> isolate,
fml::RefPtr<fml::TaskRunner> runner)
: isolate_(std::move(isolate)), runner_(std::move(runner)) {}
fml::RefPtr<fml::TaskRunner> runner);

~AutoIsolateShutdown() {
if (!IsValid()) {
return;
}
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
runner_, [isolate = std::move(isolate_), &latch]() {
if (!isolate->Shutdown()) {
FML_LOG(ERROR) << "Could not shutdown isolate.";
FML_CHECK(false);
}
latch.Signal();
});
latch.Wait();
}
~AutoIsolateShutdown();

bool IsValid() const { return isolate_ != nullptr && runner_; }

FML_WARN_UNUSED_RESULT
bool RunInIsolateScope(std::function<bool(void)> closure) {
if (!IsValid()) {
return false;
}

bool result = false;
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
runner_, [this, &result, &latch, closure]() {
tonic::DartIsolateScope scope(isolate_->isolate());
tonic::DartApiScope api_scope;
if (closure) {
result = closure();
}
latch.Signal();
});
latch.Wait();
return true;
}
bool RunInIsolateScope(std::function<bool(void)> closure);

DartIsolate* get() {
FML_CHECK(isolate_);
Expand All @@ -69,130 +43,25 @@ class AutoIsolateShutdown {
FML_DISALLOW_COPY_AND_ASSIGN(AutoIsolateShutdown);
};

static void RunDartCodeInIsolate(DartVMRef& vm_ref,
std::unique_ptr<AutoIsolateShutdown>& result,
const Settings& settings,
const TaskRunners& task_runners,
std::string entrypoint,
const std::vector<std::string>& args,
const std::string& fixtures_path,
fml::WeakPtr<IOManager> io_manager = {}) {
FML_CHECK(task_runners.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

if (!vm_ref) {
return;
}

auto vm_data = vm_ref.GetVMData();

if (!vm_data) {
return;
}

auto weak_isolate = DartIsolate::CreateRootIsolate(
vm_data->GetSettings(), // settings
vm_data->GetIsolateSnapshot(), // isolate snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
io_manager, // io manager
{}, // unref queue
{}, // image decoder
"main.dart", // advisory uri
"main", // advisory entrypoint
nullptr, // flags
settings.isolate_create_callback, // isolate create callback
settings.isolate_shutdown_callback // isolate shutdown callback
);

auto root_isolate = std::make_unique<AutoIsolateShutdown>(
weak_isolate.lock(), task_runners.GetUITaskRunner());

if (!root_isolate->IsValid()) {
FML_LOG(ERROR) << "Could not create isolate.";
return;
}

if (root_isolate->get()->GetPhase() != DartIsolate::Phase::LibrariesSetup) {
FML_LOG(ERROR) << "Created isolate is in unexpected phase.";
return;
}

if (!DartVM::IsRunningPrecompiledCode()) {
auto kernel_file_path =
fml::paths::JoinPaths({fixtures_path, "kernel_blob.bin"});

if (!fml::IsFile(kernel_file_path)) {
FML_LOG(ERROR) << "Could not locate kernel file.";
return;
}

auto kernel_file = fml::OpenFile(kernel_file_path.c_str(), false,
fml::FilePermission::kRead);

if (!kernel_file.is_valid()) {
FML_LOG(ERROR) << "Kernel file descriptor was invalid.";
return;
}

auto kernel_mapping = std::make_unique<fml::FileMapping>(kernel_file);

if (kernel_mapping->GetMapping() == nullptr) {
FML_LOG(ERROR) << "Could not setup kernel mapping.";
return;
}

if (!root_isolate->get()->PrepareForRunningFromKernel(
std::move(kernel_mapping))) {
FML_LOG(ERROR)
<< "Could not prepare to run the isolate from the kernel file.";
return;
}
} else {
if (!root_isolate->get()->PrepareForRunningFromPrecompiledCode()) {
FML_LOG(ERROR)
<< "Could not prepare to run the isolate from precompiled code.";
return;
}
}
void RunDartCodeInIsolate(DartVMRef& vm_ref,
std::unique_ptr<AutoIsolateShutdown>& result,
const Settings& settings,
const TaskRunners& task_runners,
std::string entrypoint,
const std::vector<std::string>& args,
const std::string& fixtures_path,
fml::WeakPtr<IOManager> io_manager = {});

if (root_isolate->get()->GetPhase() != DartIsolate::Phase::Ready) {
FML_LOG(ERROR) << "Isolate is in unexpected phase.";
return;
}

if (!root_isolate->get()->Run(entrypoint, args,
settings.root_isolate_create_callback)) {
FML_LOG(ERROR) << "Could not run the method \"" << entrypoint
<< "\" in the isolate.";
return;
}

root_isolate->get()->AddIsolateShutdownCallback(
settings.root_isolate_shutdown_callback);

result = std::move(root_isolate);
}

static std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolate(
std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolate(
DartVMRef& vm_ref,
const Settings& settings,
const TaskRunners& task_runners,
std::string entrypoint,
const std::vector<std::string>& args,
const std::string& fixtures_path,
fml::WeakPtr<IOManager> io_manager = {}) {
std::unique_ptr<AutoIsolateShutdown> result;
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetPlatformTaskRunner(), fml::MakeCopyable([&]() mutable {
RunDartCodeInIsolate(vm_ref, result, settings, task_runners, entrypoint,
args, fixtures_path, io_manager);
latch.Signal();
}));
latch.Wait();
return result;
}
fml::WeakPtr<IOManager> io_manager = {});

} // namespace testing
} // namespace flutter

#endif // FLUTTER_TESTING_DART_ISOLATE_RUNNER_H_