Flutter Engine
dart_runner.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "dart_runner.h"
6 
7 #include <lib/async-loop/loop.h>
8 #include <lib/async/default.h>
9 #include <lib/syslog/global.h>
10 #include <sys/stat.h>
11 #include <zircon/status.h>
12 #include <zircon/syscalls.h>
13 
14 #include <cerrno>
15 #include <memory>
16 #include <thread>
17 #include <utility>
18 
21 #include "flutter/fml/trace_event.h"
22 #include "logging.h"
25 #include "service_isolate.h"
26 #include "third_party/dart/runtime/include/bin/dart_io_api.h"
29 
30 #if defined(AOT_RUNTIME)
31 extern "C" uint8_t _kDartVmSnapshotData[];
32 extern "C" uint8_t _kDartVmSnapshotInstructions[];
33 #endif
34 
35 namespace dart_runner {
36 
37 namespace {
38 
39 const char* kDartVMArgs[] = {
40  // clang-format off
41  "--lazy_async_stacks",
42 
43  "--systrace_timeline",
44  "--timeline_streams=Compiler,Dart,Debugger,Embedder,GC,Isolate,VM",
45 
46 #if defined(AOT_RUNTIME)
47  "--precompilation",
48 #else
49  "--enable_mirrors=false",
50 #endif
51 
52  // No asserts in debug or release product.
53  // No asserts in release with flutter_profile=true (non-product)
54  // Yes asserts in non-product debug.
55 #if !defined(DART_PRODUCT) && (!defined(FLUTTER_PROFILE) || !defined(NDEBUG))
56  "--enable_asserts",
57 #endif
58  // clang-format on
59 };
60 
61 Dart_Isolate IsolateGroupCreateCallback(const char* uri,
62  const char* name,
63  const char* package_root,
64  const char* package_config,
65  Dart_IsolateFlags* flags,
66  void* callback_data,
67  char** error) {
68  if (std::string(uri) == DART_VM_SERVICE_ISOLATE_NAME) {
69 #if defined(DART_PRODUCT)
70  *error = strdup("The service isolate is not implemented in product mode");
71  return NULL;
72 #else
73  return CreateServiceIsolate(uri, flags, error);
74 #endif
75  }
76 
77  *error = strdup("Isolate spawning is not implemented in dart_runner");
78  return NULL;
79 }
80 
81 void IsolateShutdownCallback(void* isolate_group_data, void* isolate_data) {
82  // The service isolate (and maybe later the kernel isolate) doesn't have an
83  // async loop.
84  auto dispatcher = async_get_default_dispatcher();
85  auto loop = async_loop_from_dispatcher(dispatcher);
86  if (loop) {
89  if (queue) {
90  queue->Destroy();
91  }
92 
93  async_loop_quit(loop);
94  }
95 
96  auto state =
97  static_cast<std::shared_ptr<tonic::DartState>*>(isolate_group_data);
98  state->get()->SetIsShuttingDown();
99 }
100 
101 void IsolateGroupCleanupCallback(void* isolate_group_data) {
102  delete static_cast<std::shared_ptr<tonic::DartState>*>(isolate_group_data);
103 }
104 
105 // Runs the application for a V1 component.
106 void RunApplicationV1(
107  DartRunner* runner,
108  fuchsia::sys::Package package,
109  fuchsia::sys::StartupInfo startup_info,
110  std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
111  ::fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
112  int64_t start = Dart_TimelineGetMicros();
113 
114  DartComponentController app(std::move(package), std::move(startup_info),
115  runner_incoming_services, std::move(controller));
116  bool success = app.Setup();
117 
118  int64_t end = Dart_TimelineGetMicros();
119  Dart_TimelineEvent("DartComponentController::Setup", start, end,
120  Dart_Timeline_Event_Duration, 0, NULL, NULL);
121  if (success) {
122  app.Run();
123  }
124 
125  if (Dart_CurrentIsolate()) {
126  Dart_ShutdownIsolate();
127  }
128 }
129 
130 // Runs the application for a V2 component.
131 void RunApplicationV2(
132  DartRunner* runner,
133  fuchsia::component::runner::ComponentStartInfo start_info,
134  std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
135  fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
136  controller) {
137  const int64_t start = Dart_TimelineGetMicros();
138 
139  DartComponentControllerV2 app(std::move(start_info), runner_incoming_services,
140  std::move(controller));
141  const bool success = app.SetUp();
142 
143  const int64_t end = Dart_TimelineGetMicros();
144  Dart_TimelineEvent("DartComponentControllerV2::Setup", start, end,
145  Dart_Timeline_Event_Duration, 0, NULL, NULL);
146  if (success) {
147  app.Run();
148  }
149 
150  if (Dart_CurrentIsolate()) {
151  Dart_ShutdownIsolate();
152  }
153 }
154 
155 bool EntropySource(uint8_t* buffer, intptr_t count) {
156  zx_cprng_draw(buffer, count);
157  return true;
158 }
159 
160 } // namespace
161 
162 DartRunner::DartRunner(sys::ComponentContext* context) : context_(context) {
163  context_->outgoing()->AddPublicService<fuchsia::sys::Runner>(
164  [this](fidl::InterfaceRequest<fuchsia::sys::Runner> request) {
165  bindings_.AddBinding(this, std::move(request));
166  });
167 
168  context_->outgoing()
169  ->AddPublicService<fuchsia::component::runner::ComponentRunner>(
170  [this](fidl::InterfaceRequest<
171  fuchsia::component::runner::ComponentRunner> request) {
172  component_runner_bindings_.AddBinding(this, std::move(request));
173  });
174 
175 #if !defined(DART_PRODUCT)
176  // The VM service isolate uses the process-wide namespace. It writes the
177  // vm service protocol port under /tmp. The VMServiceObject exposes that
178  // port number to The Hub.
179  context_->outgoing()->debug_dir()->AddEntry(
181  std::make_unique<dart_utils::VMServiceObject>());
182 
183 #endif // !defined(DART_PRODUCT)
184 
185  dart::bin::BootstrapDartIo();
186 
187  char* error =
188  Dart_SetVMFlags(dart_utils::ArraySize(kDartVMArgs), kDartVMArgs);
189  if (error) {
190  FX_LOGF(FATAL, LOG_TAG, "Dart_SetVMFlags failed: %s", error);
191  }
192 
193  Dart_InitializeParams params = {};
194  params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
195 #if defined(AOT_RUNTIME)
196  params.vm_snapshot_data = ::_kDartVmSnapshotData;
197  params.vm_snapshot_instructions = ::_kDartVmSnapshotInstructions;
198 #else
200  nullptr, "/pkg/data/vm_snapshot_data.bin", vm_snapshot_data_)) {
201  FX_LOG(FATAL, LOG_TAG, "Failed to load vm snapshot data");
202  }
204  nullptr, "/pkg/data/vm_snapshot_instructions.bin",
205  vm_snapshot_instructions_, true /* executable */)) {
206  FX_LOG(FATAL, LOG_TAG, "Failed to load vm snapshot instructions");
207  }
208  params.vm_snapshot_data = vm_snapshot_data_.address();
209  params.vm_snapshot_instructions = vm_snapshot_instructions_.address();
210 #endif
211  params.create_group = IsolateGroupCreateCallback;
212  params.shutdown_isolate = IsolateShutdownCallback;
213  params.cleanup_group = IsolateGroupCleanupCallback;
214  params.entropy_source = EntropySource;
215 #if !defined(DART_PRODUCT)
216  params.get_service_assets = GetVMServiceAssetsArchiveCallback;
217 #endif
218  error = Dart_Initialize(&params);
219  if (error)
220  FX_LOGF(FATAL, LOG_TAG, "Dart_Initialize failed: %s", error);
221 }
222 
224  char* error = Dart_Cleanup();
225  if (error)
226  FX_LOGF(FATAL, LOG_TAG, "Dart_Cleanup failed: %s", error);
227 }
228 
229 void DartRunner::StartComponent(
230  fuchsia::sys::Package package,
231  fuchsia::sys::StartupInfo startup_info,
232  fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
233  // TRACE_DURATION currently requires that the string data does not change
234  // in the traced scope. Since |package| gets moved in the construction of
235  // |thread| below, we cannot ensure that |package.resolved_url| does not
236  // move or change, so we make a copy to pass to TRACE_DURATION.
237  // TODO(PT-169): Remove this copy when TRACE_DURATION reads string arguments
238  // eagerly.
239  std::string url_copy = package.resolved_url;
240  TRACE_EVENT1("dart", "StartComponent", "url", url_copy.c_str());
241  std::thread thread(RunApplicationV1, this, std::move(package),
242  std::move(startup_info), context_->svc(),
243  std::move(controller));
244  thread.detach();
245 }
246 
247 void DartRunner::Start(
248  fuchsia::component::runner::ComponentStartInfo start_info,
249  fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
250  controller) {
251  std::string url_copy = start_info.resolved_url();
252  TRACE_EVENT1("dart", "Start", "url", url_copy.c_str());
253  std::thread thread(RunApplicationV2, this, std::move(start_info),
254  context_->svc(), std::move(controller));
255  thread.detach();
256 }
257 
258 } // namespace dart_runner
static DartMicrotaskQueue * GetForCurrentThread()
size_t ArraySize(T(&array)[SIZE])
Definition: inlines.h:26
const uint8_t uint32_t uint32_t GError ** error
FlutterSemanticsFlag flags
Dart_Handle GetVMServiceAssetsArchiveCallback()
static bool LoadFromNamespace(fdio_ns_t *namespc, const std::string &path, MappedResource &resource, bool executable=false)
Dart_Isolate CreateServiceIsolate(const char *uri, Dart_IsolateFlags *flags, char **error)
const uint8_t * address() const
#define LOG_TAG
Definition: logging.h:11
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
Definition: trace_event.h:94
const char * name
Definition: fuchsia.cc:50
static const uint8_t buffer[]
char * strdup(const char *str1)
static constexpr const char * kPortDirName
AtkStateType state
DartRunner(sys::ComponentContext *context)
Definition: dart_runner.cc:162