Flutter Engine
handle_exception.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 "handle_exception.h"
6 
7 #include <fuchsia/feedback/cpp/fidl.h>
8 #include <fuchsia/mem/cpp/fidl.h>
9 #include <lib/syslog/global.h>
10 #include <lib/zx/vmo.h>
11 #include <sys/types.h>
12 #include <zircon/status.h>
13 
14 #include <string>
15 
17 
18 #include "logging.h"
19 
20 namespace {
21 static bool SetStackTrace(const std::string& data,
22  fuchsia::feedback::RuntimeCrashReport* report) {
23  uint64_t num_bytes = data.size();
24  zx::vmo vmo;
25 
26  if (zx::vmo::create(num_bytes, 0u, &vmo) < 0) {
27  return false;
28  }
29 
30  if (num_bytes > 0) {
31  if (vmo.write(data.data(), 0, num_bytes) < 0) {
32  return false;
33  }
34  }
35 
36  fuchsia::mem::Buffer buffer;
37  buffer.vmo = std::move(vmo);
38  buffer.size = num_bytes;
39  report->set_exception_stack_trace(std::move(buffer));
40 
41  return true;
42 }
43 
44 fuchsia::feedback::CrashReport BuildCrashReport(
45  const std::string& component_url,
46  const std::string& error,
47  const std::string& stack_trace) {
48  // The runtime type has already been pre-pended to the error message so we
49  // expect the format to be '$RuntimeType: $Message'.
50  std::string error_type;
51  std::string error_message;
52  const size_t delimiter_pos = error.find_first_of(':');
53  if (delimiter_pos == std::string::npos) {
54  FX_LOGF(ERROR, LOG_TAG,
55  "error parsing Dart exception: expected format '$RuntimeType: "
56  "$Message', got '%s'",
57  error.c_str());
58  // We still need to specify a type, otherwise the stack trace does not
59  // show up in the crash server UI.
60  error_type = "UnknownError";
61  error_message = error;
62  } else {
63  error_type = error.substr(0, delimiter_pos);
64  error_message =
65  error.substr(delimiter_pos + 2 /*to get rid of the leading ': '*/);
66  }
67 
68  // Truncate error message to the maximum length allowed for the crash_reporter
69  // FIDL call
70  error_message = error_message.substr(
71  0, fuchsia::feedback::MAX_EXCEPTION_MESSAGE_LENGTH - 1);
72 
73  fuchsia::feedback::RuntimeCrashReport dart_report;
74  dart_report.set_exception_type(error_type);
75  dart_report.set_exception_message(error_message);
76  if (!SetStackTrace(stack_trace, &dart_report)) {
77  FX_LOG(ERROR, LOG_TAG, "Failed to convert Dart stack trace to VMO");
78  }
79 
80  fuchsia::feedback::SpecificCrashReport specific_report;
81  specific_report.set_dart(std::move(dart_report));
82  fuchsia::feedback::CrashReport report;
83  report.set_program_name(component_url);
84  report.set_specific_report(std::move(specific_report));
85  return report;
86 }
87 
88 } // namespace
89 
90 namespace dart_utils {
91 
92 void HandleIfException(std::shared_ptr<::sys::ServiceDirectory> services,
93  const std::string& component_url,
94  Dart_Handle result) {
95  if (!Dart_IsError(result) || !Dart_ErrorHasException(result)) {
96  return;
97  }
98 
99  const std::string error =
100  tonic::StdStringFromDart(Dart_ToString(Dart_ErrorGetException(result)));
101  const std::string stack_trace =
102  tonic::StdStringFromDart(Dart_ToString(Dart_ErrorGetStackTrace(result)));
103 
104  return HandleException(services, component_url, error, stack_trace);
105 }
106 
107 void HandleException(std::shared_ptr<::sys::ServiceDirectory> services,
108  const std::string& component_url,
109  const std::string& error,
110  const std::string& stack_trace) {
111  fuchsia::feedback::CrashReport crash_report =
112  BuildCrashReport(component_url, error, stack_trace);
113 
114  fuchsia::feedback::CrashReporterPtr crash_reporter =
115  services->Connect<fuchsia::feedback::CrashReporter>();
116  crash_reporter->File(
117  std::move(crash_report),
118  [](fuchsia::feedback::CrashReporter_File_Result result) {
119  if (result.is_err()) {
120  FX_LOGF(ERROR, LOG_TAG, "Failed to report Dart exception: %d (%s)",
121  result.err(), zx_status_get_string(result.err()));
122  }
123  });
124 }
125 
126 } // namespace dart_utils
void HandleException(std::shared_ptr<::sys::ServiceDirectory > services, const std::string &component_url, const std::string &error, const std::string &stack_trace)
FlMethodResponse GError ** error
std::string StdStringFromDart(Dart_Handle handle)
void HandleIfException(std::shared_ptr<::sys::ServiceDirectory > services, const std::string &component_url, Dart_Handle result)
#define LOG_TAG
Definition: logging.h:11