Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
service_isolate.cc
Go to the documentation of this file.
1// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
6
8#include "vm/dart_api_impl.h"
10#include "vm/dart_entry.h"
11#include "vm/isolate.h"
12#include "vm/lockers.h"
13#include "vm/message.h"
14#include "vm/message_handler.h"
15#include "vm/message_snapshot.h"
16#include "vm/native_arguments.h"
17#include "vm/native_entry.h"
18#include "vm/object.h"
19#include "vm/object_store.h"
20#include "vm/port.h"
21#include "vm/service.h"
22#include "vm/symbols.h"
23#include "vm/thread_pool.h"
24#include "vm/timeline.h"
25
26#if !defined(PRODUCT)
27
28namespace dart {
29
30#define Z (T->zone())
31
32DEFINE_FLAG(bool, trace_service, false, "Trace VM service requests.");
34 trace_service_pause_events,
35 false,
36 "Trace VM service isolate pause events.");
38 trace_service_verbose,
39 false,
40 "Provide extra service tracing information.");
41
42// These must be kept in sync with service/constants.dart
43#define VM_SERVICE_ISOLATE_EXIT_MESSAGE_ID 0
44#define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1
45#define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2
46
47#define VM_SERVICE_WEB_SERVER_CONTROL_MESSAGE_ID 3
48#define VM_SERVICE_SERVER_INFO_MESSAGE_ID 4
49
50#define VM_SERVICE_METHOD_CALL_FROM_NATIVE 5
51
53 Dart_Port port_id,
54 intptr_t code,
55 const char* name) {
56 Dart_CObject ccode;
58 ccode.value.as_int32 = code;
59
60 Dart_CObject port_int;
61 port_int.type = Dart_CObject_kInt64;
62 port_int.value.as_int64 = port_id;
63
64 Dart_CObject send_port;
65 send_port.type = Dart_CObject_kSendPort;
66 send_port.value.as_send_port.id = port_id;
67 send_port.value.as_send_port.origin_id = port_id;
68
69 Dart_CObject cname;
71 cname.value.as_string = const_cast<char*>(name);
72
73 Dart_CObject* values[4];
74 values[0] = &ccode;
75 values[1] = &port_int;
76 values[2] = &send_port;
77 values[3] = &cname;
78
81 message.value.as_array.length = 4;
82 message.value.as_array.values = values;
83
86}
87
88static ArrayPtr MakeServerControlMessage(const SendPort& sp,
89 intptr_t code,
90 bool enable,
91 const Bool& silenceOutput) {
92 const Array& list = Array::Handle(Array::New(4));
93 ASSERT(!list.IsNull());
94 list.SetAt(0, Integer::Handle(Integer::New(code)));
95 list.SetAt(1, sp);
96 list.SetAt(2, Bool::Get(enable));
97 list.SetAt(3, silenceOutput);
98 return list.ptr();
99}
100
103 nullptr;
104Monitor* ServiceIsolate::monitor_ = new Monitor();
106Isolate* ServiceIsolate::isolate_ = nullptr;
109char* ServiceIsolate::server_address_ = nullptr;
111
114 sp, VM_SERVICE_SERVER_INFO_MESSAGE_ID, false /* ignored */,
115 Bool::Handle() /* ignored */));
116 ASSERT(!message.IsNull());
117 PortMap::PostMessage(WriteMessage(/* same_group */ false, message, port_,
119}
120
122 bool enable,
123 const Bool& silenceOutput) {
125 sp, VM_SERVICE_WEB_SERVER_CONTROL_MESSAGE_ID, enable, silenceOutput));
126 ASSERT(!message.IsNull());
127 PortMap::PostMessage(WriteMessage(/* same_group */ false, message, port_,
129}
130
131void ServiceIsolate::SetServerAddress(const char* address) {
132 if (server_address_ != nullptr) {
133 free(server_address_);
134 server_address_ = nullptr;
135 }
136 if (address == nullptr) {
137 return;
138 }
140}
141
144 return isolate_ != nullptr;
145}
146
149 return (port_ != ILLEGAL_PORT) && (isolate_ != nullptr);
150}
151
154 return isolate->origin_id() == origin_;
155}
156
161
164 while (state_ == kStarting) {
165 ml.Wait();
166 }
167}
168
169bool ServiceIsolate::SendServiceRpc(uint8_t* request_json,
170 intptr_t request_json_length,
171 Dart_Port reply_port,
172 char** error) {
173 // Keep in sync with "sdk/lib/vmservice/vmservice.dart:_handleNativeRpcCall".
174 Dart_CObject opcode;
175 opcode.type = Dart_CObject_kInt32;
177
180 message.value.as_typed_data.type = Dart_TypedData_kUint8;
181 message.value.as_typed_data.length = request_json_length;
182 message.value.as_typed_data.values = request_json;
183
184 Dart_CObject send_port;
185 send_port.type = Dart_CObject_kSendPort;
186 send_port.value.as_send_port.id = reply_port;
188
189 Dart_CObject* request_array[] = {
190 &opcode,
191 &message,
192 &send_port,
193 };
194
195 Dart_CObject request;
196 request.type = Dart_CObject_kArray;
197 request.value.as_array.values = request_array;
198 request.value.as_array.length = ARRAY_SIZE(request_array);
200 Dart_Port service_port = ServiceIsolate::Port();
201 bool success = false;
202 if (service_port != ILLEGAL_PORT) {
203 success = Dart_PostCObject(service_port, &request);
204 if (!success && error != nullptr) {
205 *error = Utils::StrDup("Was unable to post message to service isolate.");
206 }
207 } else {
208 if (error != nullptr) {
209 if (startup_failure_reason_ != nullptr) {
210 *error = OS::SCreate(/*zone=*/nullptr,
211 "Service isolate failed to start up: %s.",
213 } else {
214 *error = Utils::StrDup("No service isolate port was found.");
215 }
216 }
217 }
218 return success;
219}
220
222 if (!IsRunning()) {
223 return false;
224 }
225 Thread* thread = Thread::Current();
226 Isolate* isolate = thread->isolate();
227 if (isolate->is_vm_isolate()) {
228 return false;
229 }
230
231 Dart_Port main_port = Dart_GetMainPortId();
232 if (FLAG_trace_service) {
234 " registered.\n",
235 isolate->name(), main_port);
236 }
237 bool result = SendServiceControlMessage(thread, main_port,
239 isolate->name());
240 isolate->set_is_service_registered(true);
241 return result;
242}
243
245 if (!IsRunning()) {
246 return false;
247 }
248 Thread* thread = Thread::Current();
249 Isolate* isolate = thread->isolate();
250 if (isolate->is_vm_isolate()) {
251 return false;
252 }
253
254 Dart_Port main_port = isolate->main_port();
255 if (FLAG_trace_service) {
257 " deregistered.\n",
258 isolate->name(), main_port);
259 }
260 isolate->set_is_service_registered(false);
261 return SendServiceControlMessage(thread, main_port,
263 isolate->name());
264}
265
267 if (!IsRunning()) {
268 return;
269 }
270 if (FLAG_trace_service) {
272 ": sending service exit message.\n");
273 }
274
275 Dart_CObject code;
276 code.type = Dart_CObject_kInt32;
277 code.value.as_int32 = VM_SERVICE_ISOLATE_EXIT_MESSAGE_ID;
278 Dart_CObject* values[1] = {&code};
279
282 message.value.as_array.length = 1;
283 message.value.as_array.values = values;
284
288}
289
294
297 isolate_ = isolate;
298 if (isolate_ != nullptr) {
299 ASSERT(isolate->is_service_isolate());
301 }
302}
303
306 ASSERT(I == T->isolate());
307 ASSERT(I != nullptr);
308 ASSERT(I->name() != nullptr);
309 if (!I->is_service_isolate()) {
310 // Not service isolate.
311 return;
312 }
313 if (Exists()) {
314 // Service isolate already exists.
315 return;
316 }
318}
319
328
335
344
346 public:
347 virtual void Run() {
348 ASSERT(Isolate::Current() == nullptr);
349#if defined(SUPPORT_TIMELINE)
350 TimelineBeginEndScope tbes(Timeline::GetVMStream(),
351 "ServiceIsolateStartup");
352#endif // SUPPORT_TIMELINE
353 char* error = nullptr;
354 Isolate* isolate = nullptr;
355
356 const auto create_group_callback = ServiceIsolate::create_group_callback();
357 ASSERT(create_group_callback != nullptr);
358
359 Dart_IsolateFlags api_flags;
360 Isolate::FlagsInitialize(&api_flags);
361 api_flags.is_system_isolate = true;
362 api_flags.is_service_isolate = true;
363 isolate = reinterpret_cast<Isolate*>(
364 create_group_callback(ServiceIsolate::kName, ServiceIsolate::kName,
365 nullptr, nullptr, &api_flags, nullptr, &error));
366 if (isolate == nullptr) {
367 if (FLAG_trace_service) {
369 ": Isolate creation error: %s\n",
370 error);
371 }
372
373 char* formatted_error = OS::SCreate(
374 /*zone=*/nullptr, "Invoking the 'create_group' failed with: '%s'",
375 error);
376
377 free(error);
378 error = nullptr;
379 ServiceIsolate::InitializingFailed(formatted_error);
380 return;
381 }
382
383 bool got_unwind;
384 {
385 ASSERT(Isolate::Current() == nullptr);
386 StartIsolateScope start_scope(isolate);
387 got_unwind = RunMain(isolate);
388 }
389
390 // FinishedInitializing should be called irrespective of whether
391 // running main caused an error or not. Otherwise, other isolates
392 // waiting for service isolate to come up will deadlock.
394
395 if (got_unwind) {
396 ShutdownIsolate(reinterpret_cast<uword>(isolate));
397 return;
398 }
399
400 isolate->message_handler()->Run(isolate->group()->thread_pool(), nullptr,
402 reinterpret_cast<uword>(isolate));
403 }
404
405 protected:
406 static void ShutdownIsolate(uword parameter) {
407 if (FLAG_trace_service) {
408 OS::PrintErr("vm-service: ShutdownIsolate\n");
409 }
410 Dart_EnterIsolate(reinterpret_cast<Dart_Isolate>(parameter));
411 {
412 auto T = Thread::Current();
413 TransitionNativeToVM transition(T);
414 StackZone zone(T);
415 HandleScope handle_scope(T);
416
417 auto I = T->isolate();
418 ASSERT(I->is_service_isolate());
419
420 // Print the error if there is one. This may execute dart code to
421 // print the exception object, so we need to use a StartIsolateScope.
423 error = T->sticky_error();
424 if (!error.IsNull() && !error.IsUnwindError()) {
426 error.ToErrorCString());
427 }
428 error = I->sticky_error();
429 if (!error.IsNull() && !error.IsUnwindError()) {
431 error.ToErrorCString());
432 }
433 }
435 if (FLAG_trace_service) {
437 }
439 }
440
443 ASSERT(I == T->isolate());
444 StackZone zone(T);
445 // Invoke main which will set up the service port.
446 const Library& root_library =
447 Library::Handle(Z, I->group()->object_store()->root_library());
448 if (root_library.IsNull()) {
449 if (FLAG_trace_service) {
451 ": Embedder did not install a script.");
452 }
453 // Service isolate is not supported by embedder.
454 return false;
455 }
456 ASSERT(!root_library.IsNull());
457 const String& entry_name = String::Handle(Z, String::New("main"));
458 ASSERT(!entry_name.IsNull());
459 const Function& entry = Function::Handle(
460 Z, root_library.LookupFunctionAllowPrivate(entry_name));
461 if (entry.IsNull()) {
462 // Service isolate is not supported by embedder.
463 if (FLAG_trace_service) {
465 ": Embedder did not provide a main function.");
466 }
467 return false;
468 }
469 ASSERT(!entry.IsNull());
471 Z, DartEntry::InvokeFunction(entry, Object::empty_array()));
472 if (result.IsError()) {
473 // Service isolate did not initialize properly.
474 if (FLAG_trace_service) {
475 const Error& error = Error::Cast(result);
477 ": Calling main resulted in an error: %s",
478 error.ToErrorCString());
479 }
480 if (result.IsUnwindError()) {
481 return true;
482 }
483 return false;
484 }
485 return false;
486 }
487};
488
490 {
494 ml.NotifyAll();
495 }
496 // Grab the isolate create callback here to avoid race conditions with tests
497 // that change this after Dart_Initialize returns.
499 if (create_group_callback_ == nullptr) {
501 Utils::StrDup("The 'create_group' callback was not provided"));
502 return;
503 }
504 bool task_started = Dart::thread_pool()->Run<RunServiceTask>();
505 ASSERT(task_started);
506}
507
508void ServiceIsolate::KillServiceIsolate() {
509 {
511 if (state_ == kStopped) {
512 return;
513 }
516 ml.NotifyAll();
517 }
519 {
520 MonitorLocker ml(monitor_);
521 while (state_ == kStopping) {
522 ml.Wait();
523 }
525 }
526}
527
529 {
531 while (state_ == kStarting) {
532 ml.Wait();
533 }
534 }
535
536 if (IsRunning()) {
537 {
541 ml.NotifyAll();
542 }
544 {
546 while (state_ == kStopping) {
547 ml.Wait();
548 }
550 }
551 } else {
552 if (isolate_ != nullptr) {
553 // TODO(johnmccutchan,turnidge) When it is possible to properly create
554 // the VMService object and set up its shutdown handler in the service
555 // isolate's main() function, this case will no longer be possible and
556 // can be removed.
557 KillServiceIsolate();
558 }
559 }
560 if (server_address_ != nullptr) {
561 free(server_address_);
562 server_address_ = nullptr;
563 }
564
565 if (startup_failure_reason_ != nullptr) {
567 startup_failure_reason_ = nullptr;
568 }
569}
570
572 Thread* thread = Thread::Current();
573 const Library& vmservice_library =
574 Library::Handle(Library::LookupLibrary(thread, Symbols::DartVMService()));
575 ASSERT(!vmservice_library.IsNull());
576 const String& boot_function_name = String::Handle(String::New("boot"));
577 const Function& boot_function = Function::Handle(
578 vmservice_library.LookupFunctionAllowPrivate(boot_function_name));
579 ASSERT(!boot_function.IsNull());
581 DartEntry::InvokeFunction(boot_function, Object::empty_array()));
582 ASSERT(!result.IsNull());
583 if (result.IsUnwindError() || result.IsUnhandledException()) {
585 }
586 Dart_Port port = ILLEGAL_PORT;
587 if (result.IsReceivePort()) {
588 port = ReceivePort::Cast(result).Id();
589 }
590 ASSERT(port != ILLEGAL_PORT);
592}
593
595 const GrowableArray<Dart_Port>& isolate_ports,
596 const GrowableArray<const String*>& isolate_names) {
597 auto thread = Thread::Current();
598 auto zone = thread->zone();
599
600 ASSERT(thread->isolate()->is_service_isolate());
601
602 // Obtain "_registerIsolate" function to call.
603 const String& library_url = Symbols::DartVMService();
604 ASSERT(!library_url.IsNull());
605 const Library& library =
606 Library::Handle(zone, Library::LookupLibrary(thread, library_url));
607 ASSERT(!library.IsNull());
608 const String& function_name =
609 String::Handle(zone, String::New("_registerIsolate"));
610 ASSERT(!function_name.IsNull());
611 const Function& register_function_ =
613 ASSERT(!register_function_.IsNull());
614
615 Integer& port_int = Integer::Handle(zone);
616 SendPort& send_port = SendPort::Handle(zone);
617 Array& args = Array::Handle(zone, Array::New(3));
619
620 ASSERT(isolate_ports.length() == isolate_names.length());
621 for (intptr_t i = 0; i < isolate_ports.length(); ++i) {
622 const Dart_Port port_id = isolate_ports[i];
623 const String& name = *isolate_names[i];
624
625 port_int = Integer::New(port_id);
626 send_port = SendPort::New(port_id);
627 args.SetAt(0, port_int);
628 args.SetAt(1, send_port);
629 args.SetAt(2, name);
630 result = DartEntry::InvokeFunction(register_function_, args);
631 if (FLAG_trace_service) {
632 OS::PrintErr("vm-service: Isolate %s %" Pd64 " registered.\n",
633 name.ToCString(), port_id);
634 }
635 ASSERT(!result.IsError());
636 }
637}
638
640
641} // namespace dart
642
643#endif // !defined(PRODUCT)
#define Z
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
Definition object.h:10933
void SetAt(intptr_t index, const Object &value) const
Definition object.h:10858
intptr_t length() const
static const Bool & Get(bool value)
Definition object.h:10780
static ObjectPtr InvokeFunction(const Function &function, const Array &arguments)
Definition dart_entry.cc:31
static ThreadPool * thread_pool()
Definition dart.h:73
static DART_NORETURN void PropagateError(const Error &error)
static IntegerPtr New(const String &str, Heap::Space space=Heap::kNew)
Definition object.cc:23063
MutatorThreadPool * thread_pool()
Definition isolate.h:736
static Isolate * Current()
Definition isolate.h:939
static void KillIfExists(Isolate *isolate, LibMsgId msg_id)
Definition isolate.cc:3660
MessageHandler * message_handler() const
Definition isolate.cc:2380
bool is_vm_isolate() const
Definition isolate.h:1333
static void FlagsInitialize(Dart_IsolateFlags *api_flags)
Definition isolate.cc:1612
IsolateGroup * group() const
Definition isolate.h:990
static Dart_IsolateGroupCreateCallback CreateGroupCallback()
Definition isolate.h:1156
void set_is_service_registered(bool value)
Definition isolate.h:1341
Dart_Port origin_id()
Definition isolate.cc:1954
Dart_Port main_port() const
Definition isolate.h:1001
const char * name() const
Definition isolate.h:996
FunctionPtr LookupFunctionAllowPrivate(const String &name) const
Definition object.cc:14131
static LibraryPtr LookupLibrary(Thread *thread, const String &url)
Definition object.cc:14646
bool Run(ThreadPool *pool, StartCallback start_callback, EndCallback end_callback, CallbackData data)
@ kNormalPriority
Definition message.h:28
Monitor::WaitResult Wait(int64_t millis=Monitor::kNoTimeout)
Definition lockers.h:172
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
ObjectPtr ptr() const
Definition object.h:332
bool IsNull() const
Definition object.h:363
static Object & Handle()
Definition object.h:407
static bool PostMessage(std::unique_ptr< Message > message, bool before_events=false)
Definition port.cc:152
static void ShutdownIsolate(uword parameter)
bool RunMain(Isolate *I)
static SendPortPtr New(Dart_Port id, Heap::Space space=Heap::kNew)
Definition object.cc:25891
static Dart_Port origin_
static void FinishedExiting()
static void ControlWebServer(const SendPort &sp, bool enable, const Bool &silenceOutput)
static void SetServiceIsolate(Isolate *isolate)
static void RequestServerInfo(const SendPort &sp)
static bool SendIsolateStartupMessage()
static void VisitObjectPointers(ObjectPointerVisitor *visitor)
static Monitor * monitor_
static const char * kName
static bool SendServiceControlMessage(Thread *thread, Dart_Port port_id, intptr_t code, const char *name)
static void FinishedInitializing()
static bool SendIsolateShutdownMessage()
static char * server_address_
static Dart_IsolateGroupCreateCallback create_group_callback()
static bool IsServiceIsolateDescendant(Isolate *isolate)
static void RegisterRunningIsolates(const GrowableArray< Dart_Port > &isolate_ports, const GrowableArray< const String * > &isolate_names)
static Dart_Port Port()
static Dart_Port port_
static Dart_IsolateGroupCreateCallback create_group_callback_
static void WaitForServiceIsolateStartup()
static bool SendServiceRpc(uint8_t *request_json, intptr_t request_json_length, Dart_Port reply_port, char **error)
static void SetServerAddress(const char *address)
static void InitializingFailed(char *error)
static void SetServicePort(Dart_Port port)
static Isolate * isolate_
static void MaybeMakeServiceIsolate(Isolate *isolate)
static void SendServiceExitMessage()
static void BootVmServiceLibrary()
static char * startup_failure_reason_
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition object.cc:23777
bool Run(Args &&... args)
Definition thread_pool.h:45
Zone * zone() const
static Thread * Current()
Definition thread.h:361
Isolate * isolate() const
Definition thread.h:533
static char * StrDup(const char *s)
Dart_Isolate(* Dart_IsolateGroupCreateCallback)(const char *script_uri, const char *main, const char *package_root, const char *package_config, Dart_IsolateFlags *flags, void *isolate_data, char **error)
Definition dart_api.h:653
#define ILLEGAL_PORT
Definition dart_api.h:1530
int64_t Dart_Port
Definition dart_api.h:1524
struct _Dart_Isolate * Dart_Isolate
Definition dart_api.h:88
@ Dart_TypedData_kUint8
Definition dart_api.h:2606
#define DART_VM_SERVICE_ISOLATE_NAME
Definition dart_api.h:3831
@ Dart_CObject_kInt64
@ Dart_CObject_kTypedData
@ Dart_CObject_kSendPort
@ Dart_CObject_kString
@ Dart_CObject_kArray
@ Dart_CObject_kInt32
#define ASSERT(E)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
#define DEFINE_FLAG(type, name, default_value, comment)
Definition flags.h:16
Win32Message message
const char *const name
DART_EXPORT Dart_Port Dart_GetMainPortId()
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
uintptr_t uword
Definition globals.h:501
static ArrayPtr MakeServerControlMessage(const SendPort &sp, intptr_t code, bool enable, const Bool &silenceOutput)
std::unique_ptr< Message > WriteMessage(bool same_group, const Object &obj, Dart_Port dest_port, Message::Priority priority)
std::unique_ptr< Message > WriteApiMessage(Zone *zone, Dart_CObject *obj, Dart_Port dest_port, Message::Priority priority)
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject *message)
const char *const function_name
DART_EXPORT void Dart_ShutdownIsolate()
#define Pd64
Definition globals.h:416
#define T
bool is_service_isolate
Definition dart_api.h:593
Definition SkMD5.cpp:134
struct _Dart_CObject::@86::@87 as_send_port
union _Dart_CObject::@86 value
Dart_CObject_Type type
const char * as_string
struct _Dart_CObject::@86::@89 as_array
struct _Dart_CObject ** values
Dart_Port origin_id
#define VM_SERVICE_WEB_SERVER_CONTROL_MESSAGE_ID
#define VM_SERVICE_ISOLATE_EXIT_MESSAGE_ID
#define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID
#define VM_SERVICE_METHOD_CALL_FROM_NATIVE
#define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID
#define VM_SERVICE_SERVER_INFO_MESSAGE_ID
#define ARRAY_SIZE(array)
Definition globals.h:72