[dart][crash] send unhandled exceptions to crash analyzer
DX-246 #comment
TESTED=`run fuchsia-pkg://fuchsia.com/crasher_dart#meta/crasher_dart.cmx crasher_dart async` (report id 97d276698a970ec5)
Change-Id: I97cd2852de673007af9c0ba8907411739e7a7649
diff --git a/runtime/dart/utils/BUILD.gn b/runtime/dart/utils/BUILD.gn
new file mode 100644
index 0000000..48ee3f4
--- /dev/null
+++ b/runtime/dart/utils/BUILD.gn
@@ -0,0 +1,23 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("utils") {
+ sources = [
+ "handle_exception.cc",
+ "handle_exception.h",
+ ]
+
+ public_deps = [
+ "//garnet/public/lib/component/cpp",
+ "//zircon/public/lib/zx",
+ ]
+
+ deps = [
+ "//garnet/public/lib/fsl",
+ "//garnet/public/lib/fxl",
+ "//third_party/tonic",
+ "//zircon/public/fidl/fuchsia-crash",
+ "//zircon/public/fidl/fuchsia-mem",
+ ]
+}
diff --git a/runtime/dart/utils/handle_exception.cc b/runtime/dart/utils/handle_exception.cc
new file mode 100644
index 0000000..2c1eb38
--- /dev/null
+++ b/runtime/dart/utils/handle_exception.cc
@@ -0,0 +1,59 @@
+// Copyright 2018 The Fuchsia 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 "handle_exception.h"
+
+#include <string>
+
+#include <fuchsia/crash/cpp/fidl.h>
+#include <fuchsia/mem/cpp/fidl.h>
+#include <lib/fsl/vmo/strings.h>
+#include <lib/fxl/logging.h>
+#include <sys/types.h>
+#include <third_party/tonic/converter/dart_converter.h>
+#include <zircon/errors.h>
+#include <zircon/status.h>
+
+namespace fuchsia {
+namespace dart {
+
+zx_status_t HandleIfException(component::StartupContext* context,
+ const std::string& component_url,
+ Dart_Handle result) {
+ if (!Dart_IsError(result) || !Dart_ErrorHasException(result)) {
+ return ZX_OK;
+ }
+
+ const std::string error =
+ tonic::StdStringFromDart(Dart_ToString(Dart_ErrorGetException(result)));
+ fuchsia::mem::Buffer stack_trace;
+ if (!fsl::VmoFromString(tonic::StdStringFromDart(
+ Dart_ToString(Dart_ErrorGetStackTrace(result))),
+ &stack_trace)) {
+ FXL_LOG(ERROR) << "failed to convert Dart stack trace to VMO";
+ return ZX_ERR_INTERNAL;
+ }
+
+ fuchsia::crash::AnalyzerSyncPtr analyzer;
+ context->ConnectToEnvironmentService(analyzer.NewRequest());
+ FXL_DCHECK(analyzer);
+
+ zx_status_t out_status;
+ const zx_status_t status = analyzer->HandleManagedRuntimeException(
+ fuchsia::crash::ManagedRuntimeLanguage::DART, component_url, error,
+ std::move(stack_trace), &out_status);
+ if (status != ZX_OK) {
+ FXL_LOG(ERROR) << "failed to connect to crash analyzer: " << status << " ("
+ << zx_status_get_string(status) << ")";
+ return ZX_ERR_INTERNAL;
+ } else if (out_status != ZX_OK) {
+ FXL_LOG(ERROR) << "failed to handle Dart exception: " << out_status << " ("
+ << zx_status_get_string(out_status) << ")";
+ return ZX_ERR_INTERNAL;
+ }
+ return ZX_OK;
+}
+
+} // namespace dart
+} // namespace fuchsia
diff --git a/runtime/dart/utils/handle_exception.h b/runtime/dart/utils/handle_exception.h
new file mode 100644
index 0000000..b5766ca
--- /dev/null
+++ b/runtime/dart/utils/handle_exception.h
@@ -0,0 +1,28 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOPAZ_RUNTIME_DART_UTILS_HANDLE_EXCEPTION_H_
+#define TOPAZ_RUNTIME_DART_UTILS_HANDLE_EXCEPTION_H_
+
+#include <string>
+
+#include <lib/component/cpp/startup_context.h>
+#include <sys/types.h>
+#include <third_party/dart/runtime/include/dart_api.h>
+
+namespace fuchsia {
+namespace dart {
+
+// If |result| is a Dart Exception, passes the exception message and stack trace
+// to the crash analyzer service for further handling.
+//
+// Otherwise early returns with OK status.
+zx_status_t HandleIfException(component::StartupContext* context,
+ const std::string& component_url,
+ Dart_Handle result);
+
+} // namespace dart
+} // namespace fuchsia
+
+#endif // TOPAZ_RUNTIME_DART_UTILS_HANDLE_EXCEPTION_H_
diff --git a/runtime/dart_runner/BUILD.gn b/runtime/dart_runner/BUILD.gn
index 8ccdba0..a376230 100644
--- a/runtime/dart_runner/BUILD.gn
+++ b/runtime/dart_runner/BUILD.gn
@@ -48,6 +48,7 @@
"//garnet/public/lib/fxl",
"//garnet/public/lib/svc/cpp",
"//topaz/lib/deprecated_loop",
+ "//topaz/runtime/dart/utils",
"//third_party/tonic",
"//topaz/public/dart-pkg/fuchsia",
"//zircon/public/lib/trace-provider",
@@ -124,7 +125,8 @@
"//third_party/dart/runtime/observatory:observatory_archive"
observatory_archive_dir = get_label_info(observatory_target, "target_gen_dir")
observatory_archive_name = get_label_info(observatory_target, "name")
-observatory_archive_file = "${observatory_archive_dir}/${observatory_archive_name}.tar"
+observatory_archive_file =
+ "${observatory_archive_dir}/${observatory_archive_name}.tar"
template("aot_runner_package") {
assert(defined(invoker.product), "The parameter 'product' must be defined")
@@ -210,9 +212,7 @@
"kernel:kernel_core_snapshot${product_suffix}",
]
if (!invoker.product) {
- deps += [
- observatory_target,
- ]
+ deps += [ observatory_target ]
}
binary = "dart_${jit_or_dbc}${product_suffix}_runner"
diff --git a/runtime/dart_runner/builtin_libraries.cc b/runtime/dart_runner/builtin_libraries.cc
index 5bfab87..29929f9 100644
--- a/runtime/dart_runner/builtin_libraries.cc
+++ b/runtime/dart_runner/builtin_libraries.cc
@@ -10,11 +10,11 @@
#include "dart-pkg/fuchsia/sdk_ext/fuchsia.h"
#include "lib/fxl/arraysize.h"
#include "lib/fxl/logging.h"
+#include "third_party/dart/runtime/bin/io_natives.h"
+#include "third_party/dart/runtime/include/dart_api.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_microtask_queue.h"
#include "third_party/tonic/logging/dart_error.h"
-#include "third_party/dart/runtime/bin/io_natives.h"
-#include "third_party/dart/runtime/include/dart_api.h"
#include "topaz/lib/deprecated_loop/message_loop.h"
using tonic::ToDart;
@@ -91,13 +91,11 @@
void InitBuiltinLibrariesForIsolate(
const std::string& script_uri, fdio_ns_t* namespc, int stdoutfd,
- int stderrfd, std::unique_ptr<component::StartupContext> context,
+ int stderrfd, fidl::InterfaceHandle<fuchsia::sys::Environment> environment,
fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> outgoing_services,
bool service_isolate) {
// dart:fuchsia --------------------------------------------------------------
if (!service_isolate) {
- fidl::InterfaceHandle<fuchsia::sys::Environment> environment;
- context->ConnectToEnvironmentService(environment.NewRequest());
fuchsia::dart::Initialize(std::move(environment),
std::move(outgoing_services));
}
diff --git a/runtime/dart_runner/builtin_libraries.h b/runtime/dart_runner/builtin_libraries.h
index 1dceff0..7f6e9b5 100644
--- a/runtime/dart_runner/builtin_libraries.h
+++ b/runtime/dart_runner/builtin_libraries.h
@@ -17,7 +17,7 @@
void InitBuiltinLibrariesForIsolate(
const std::string& script_uri, fdio_ns_t* namespc, int stdoutfd,
- int stderrfd, std::unique_ptr<component::StartupContext> context,
+ int stderrfd, fidl::InterfaceHandle<fuchsia::sys::Environment> environment,
fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> outgoing_services,
bool service_isolate);
diff --git a/runtime/dart_runner/dart_component_controller.cc b/runtime/dart_runner/dart_component_controller.cc
index 7b3559d..11a5d3d 100644
--- a/runtime/dart_runner/dart_component_controller.cc
+++ b/runtime/dart_runner/dart_component_controller.cc
@@ -28,7 +28,9 @@
#include "third_party/tonic/dart_state.h"
#include "third_party/tonic/logging/dart_error.h"
#include "topaz/lib/deprecated_loop/message_loop.h"
-#include "topaz/runtime/dart_runner/builtin_libraries.h"
+#include "topaz/runtime/dart/utils/handle_exception.h"
+
+#include "builtin_libraries.h"
using tonic::ToDart;
@@ -342,9 +344,12 @@
stdoutfd_ = SetupFileDescriptor(std::move(startup_info_.launch_info.out));
stderrfd_ = SetupFileDescriptor(std::move(startup_info_.launch_info.err));
+ context_ = component::StartupContext::CreateFrom(std::move(startup_info_));
+ fidl::InterfaceHandle<fuchsia::sys::Environment> environment;
+ context_->ConnectToEnvironmentService(environment.NewRequest());
+
InitBuiltinLibrariesForIsolate(
- url_, namespace_, stdoutfd_, stderrfd_,
- component::StartupContext::CreateFrom(std::move(startup_info_)),
+ url_, namespace_, stdoutfd_, stderrfd_, std::move(environment),
std::move(outgoing_services), false /* service_isolate */);
namespace_ = nullptr;
@@ -386,6 +391,8 @@
// The program hasn't set a return code meaning this exit is unexpected.
FXL_LOG(ERROR) << Dart_GetError(main_result);
return_code_ = tonic::GetErrorExitCode(main_result);
+
+ fuchsia::dart::HandleIfException(context_.get(), url_, main_result);
}
Dart_ExitScope();
return false;
@@ -434,6 +441,8 @@
return;
}
+ fuchsia::dart::HandleIfException(context_.get(), url_, result);
+
// Otherwise, see if there was any other error.
return_code_ = tonic::GetErrorExitCode(result);
if (return_code_ != 0) {
diff --git a/runtime/dart_runner/dart_component_controller.h b/runtime/dart_runner/dart_component_controller.h
index 961fce2..551ee47 100644
--- a/runtime/dart_runner/dart_component_controller.h
+++ b/runtime/dart_runner/dart_component_controller.h
@@ -10,6 +10,7 @@
#include <lib/zx/timer.h>
#include <fuchsia/sys/cpp/fidl.h>
+#include "lib/component/cpp/startup_context.h"
#include "lib/fidl/cpp/binding.h"
#include "lib/fsl/vmo/sized_vmo.h"
#include "lib/fxl/macros.h"
@@ -60,6 +61,7 @@
std::string data_path_;
component::ServiceProviderBridge service_provider_bridge_;
fidl::Binding<fuchsia::sys::ComponentController> binding_;
+ std::unique_ptr<component::StartupContext> context_;
fdio_ns_t* namespace_ = nullptr;
int stdoutfd_ = -1;