From fa8b1de1c065aaa85d5ce7eb9a0bb33261a38f85 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Tue, 7 May 2019 13:59:43 -0700 Subject: [PATCH] Copy //runtime/dart/utils from Topaz into the engine. (flutter/engine#8871) Build rules and include paths have been updated as necessary. No other functional change. --- .../ci/licenses_golden/licenses_flutter | 12 ++ .../fuchsia/runtime/dart/utils/BUILD.gn | 44 ++++++ .../fuchsia/runtime/dart/utils/files.cc | 78 ++++++++++ .../fuchsia/runtime/dart/utils/files.h | 27 ++++ .../runtime/dart/utils/handle_exception.cc | 139 ++++++++++++++++++ .../runtime/dart/utils/handle_exception.h | 34 +++++ .../fuchsia/runtime/dart/utils/inlines.h | 32 ++++ .../fuchsia/runtime/dart/utils/logging.h | 15 ++ .../dart/utils/run_vmservice_object_tests.sh | 33 +++++ .../fuchsia/runtime/dart/utils/tempfs.cc | 89 +++++++++++ .../fuchsia/runtime/dart/utils/tempfs.h | 24 +++ .../fuchsia/runtime/dart/utils/vmo.cc | 74 ++++++++++ .../platform/fuchsia/runtime/dart/utils/vmo.h | 24 +++ .../runtime/dart/utils/vmservice_object.cc | 63 ++++++++ .../runtime/dart/utils/vmservice_object.h | 26 ++++ 15 files changed, 714 insertions(+) create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/files.cc create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/files.h create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.cc create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.h create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/inlines.h create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/logging.h create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/run_vmservice_object_tests.sh create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.cc create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.h create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.cc create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.h create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.cc create mode 100644 engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.h diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index 101f997c3c3..927f4c74a51 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -715,6 +715,18 @@ FILE: ../../../flutter/shell/platform/embedder/platform_view_embedder.cc FILE: ../../../flutter/shell/platform/embedder/platform_view_embedder.h FILE: ../../../flutter/shell/platform/embedder/vsync_waiter_embedder.cc FILE: ../../../flutter/shell/platform/embedder/vsync_waiter_embedder.h +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/files.cc +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/files.h +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.cc +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.h +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/inlines.h +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/logging.h +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.cc +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.h +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.cc +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.h +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.cc +FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.h FILE: ../../../flutter/shell/platform/glfw/client_wrapper/flutter_window_controller.cc FILE: ../../../flutter/shell/platform/glfw/client_wrapper/flutter_window_controller_unittests.cc FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn new file mode 100644 index 00000000000..9f3567c0e9a --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn @@ -0,0 +1,44 @@ +# 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. + +assert(is_fuchsia) + +import("//build/fuchsia/sdk.gni") + +config("utils_config") { + include_dirs = [ "../../.." ] +} + +source_set("utils") { + sources = [ + "files.cc", + "files.h", + "handle_exception.cc", + "handle_exception.h", + "inlines.h", + "logging.h", + "tempfs.cc", + "tempfs.h", + "vmo.cc", + "vmo.h", + "vmservice_object.cc", + "vmservice_object.h", + ] + + deps = [ + "$fuchsia_sdk_root/fidl:fuchsia.crash", + "$fuchsia_sdk_root/fidl:fuchsia.mem", + "$fuchsia_sdk_root/pkg:async-loop", + "$fuchsia_sdk_root/pkg:async-loop-cpp", + "$fuchsia_sdk_root/pkg:fdio", + "$fuchsia_sdk_root/pkg:memfs", + "$fuchsia_sdk_root/pkg:syslog", + "$fuchsia_sdk_root/pkg:zx", + "$fuchsia_sdk_root/pkg/lib/sys/cpp", + "$fuchsia_sdk_root/pkg/lib/vfs/cpp", + "//third_party/tonic", + ] + + public_configs = [ ":utils_config" ] +} diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/files.cc b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/files.cc new file mode 100644 index 00000000000..c2e9fd40141 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/files.cc @@ -0,0 +1,78 @@ +// 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 "runtime/dart/utils/files.h" + +#include +#include + +#include "runtime/dart/utils/inlines.h" +#include "runtime/dart/utils/logging.h" + +namespace dart_utils { + +namespace { + +bool ReadFileDescriptor(int fd, std::string* result) { + DEBUG_CHECK(result, LOG_TAG, ""); + result->clear(); + + if (fd < 0) { + return false; + } + + constexpr size_t kBufferSize = 1 << 16; + size_t offset = 0; + ssize_t bytes_read = 0; + do { + offset += bytes_read; + result->resize(offset + kBufferSize); + bytes_read = read(fd, &(*result)[offset], kBufferSize); + } while (bytes_read > 0); + + if (bytes_read < 0) { + result->clear(); + return false; + } + + result->resize(offset + bytes_read); + return true; +} + +bool WriteFileDescriptor(int fd, const char* data, ssize_t size) { + ssize_t total = 0; + for (ssize_t partial = 0; total < size; total += partial) { + partial = write(fd, data + total, size - total); + if (partial < 0) + return false; + } + return true; +} + +} // namespace + +bool ReadFileToString(const std::string& path, std::string* result) { + return ReadFileToStringAt(AT_FDCWD, path, result); +} + +bool ReadFileToStringAt(int dirfd, + const std::string& path, + std::string* result) { + int fd = openat(dirfd, path.c_str(), O_RDONLY); + bool status = ReadFileDescriptor(fd, result); + close(fd); + return status; +} + +bool WriteFile(const std::string& path, const char* data, ssize_t size) { + int fd = openat(AT_FDCWD, path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0666); + if (fd < 0) { + return false; + } + bool status = WriteFileDescriptor(fd, data, size); + close(fd); + return status; +} + +} // namespace dart_utils diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/files.h b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/files.h new file mode 100644 index 00000000000..2b3212e6f54 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/files.h @@ -0,0 +1,27 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_FILES_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_FILES_H_ + +#include + +namespace dart_utils { + +// Reads the contents of the file at the given path or file descriptor and +// stores the data in result. Returns true if the file was read successfully, +// otherwise returns false. If this function returns false, |result| will be +// the empty string. +bool ReadFileToString(const std::string& path, std::string* result); +bool ReadFileToStringAt(int dirfd, + const std::string& path, + std::string* result); + +// Writes the given data to the file at the given path. Returns true if the data +// was successfully written, otherwise returns false. +bool WriteFile(const std::string& path, const char* data, ssize_t size); + +} // namespace dart_utils + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_FILES_H_ diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.cc b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.cc new file mode 100644 index 00000000000..b1b62707842 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.cc @@ -0,0 +1,139 @@ +// 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 "runtime/dart/utils/handle_exception.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "runtime/dart/utils/logging.h" + +namespace { +static bool FillBuffer(const std::string& data, fuchsia::mem::Buffer* buffer) { + uint64_t num_bytes = data.size(); + zx::vmo vmo; + + if (zx::vmo::create(num_bytes, 0u, &vmo) < 0) { + return false; + } + + if (num_bytes > 0) { + if (vmo.write(data.data(), 0, num_bytes) < 0) { + return false; + } + } + + buffer->vmo = std::move(vmo); + buffer->size = num_bytes; + + return true; +} + +template +void CopyToArray(const std::string& s, std::array* arr) { + const size_t max_size = arr->size(); + auto end = s.end(); + if (s.size() > max_size) { + FX_LOGF(WARNING, LOG_TAG, "truncating '%s' to %d characters", s.c_str(), + max_size); + end = s.begin() + max_size; + } + std::copy(s.begin(), end, arr->data()); +} + +fuchsia::crash::ManagedRuntimeException BuildException( + const std::string& error, + const std::string& stack_trace) { + // The runtime type has already been pre-pended to the error message so we + // expect the format to be '$RuntimeType: $Message'. + std::string error_type; + std::string error_message; + const size_t delimiter_pos = error.find_first_of(':'); + if (delimiter_pos == std::string::npos) { + FX_LOGF(ERROR, LOG_TAG, + "error parsing Dart exception: expected format '$RuntimeType: " + "$Message', got '%s'", + error.c_str()); + // We still need to specify a type, otherwise the stack trace does not + // show up in the crash server UI. + error_type = "UnknownError"; + error_message = error; + } else { + error_type = error.substr(0, delimiter_pos); + error_message = + error.substr(delimiter_pos + 2 /*to get rid of the leading ': '*/); + } + + // Default-initialize to initialize the underlying arrays of characters with + // 0s and null-terminate the strings. + fuchsia::crash::GenericException exception = {}; + CopyToArray(error_type, &exception.type); + CopyToArray(error_message, &exception.message); + if (!FillBuffer(stack_trace, &exception.stack_trace)) { + FX_LOG(ERROR, LOG_TAG, "Failed to convert Dart stack trace to VMO"); + } + + fuchsia::crash::ManagedRuntimeException dart_exception; + dart_exception.set_dart(std::move(exception)); + return dart_exception; +} + +} // namespace + +namespace dart_utils { + +zx_status_t HandleIfException(std::shared_ptr<::sys::ServiceDirectory> services, + 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))); + const std::string stack_trace = + tonic::StdStringFromDart(Dart_ToString(Dart_ErrorGetStackTrace(result))); + + return HandleException(services, component_url, error, stack_trace); +} + +zx_status_t HandleException(std::shared_ptr<::sys::ServiceDirectory> services, + const std::string& component_url, + const std::string& error, + const std::string& stack_trace) { + fuchsia::crash::ManagedRuntimeException exception = + BuildException(error, stack_trace); + + fuchsia::crash::AnalyzerSyncPtr analyzer; + services->Connect(analyzer.NewRequest()); +#ifndef NDEBUG + if (!analyzer) { + FX_LOG(FATAL, LOG_TAG, "Could not connect to analyzer service"); + } +#endif + + fuchsia::crash::Analyzer_OnManagedRuntimeException_Result out_result; + const zx_status_t status = analyzer->OnManagedRuntimeException( + component_url, std::move(exception), &out_result); + if (status != ZX_OK) { + FX_LOGF(ERROR, LOG_TAG, "Failed to connect to crash analyzer: %d (%s)", + status, zx_status_get_string(status)); + return ZX_ERR_INTERNAL; + } else if (out_result.is_err()) { + FX_LOGF(ERROR, LOG_TAG, "Failed to handle Dart exception: %d (%s)", + out_result.err(), zx_status_get_string(out_result.err())); + return ZX_ERR_INTERNAL; + } + return ZX_OK; +} + +} // namespace dart_utils diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.h b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.h new file mode 100644 index 00000000000..4746950fe22 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.h @@ -0,0 +1,34 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_HANDLE_EXCEPTION_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_HANDLE_EXCEPTION_H_ + +#include +#include + +#include +#include +#include + +namespace dart_utils { + +// 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(std::shared_ptr<::sys::ServiceDirectory> services, + const std::string& component_url, + Dart_Handle result); + +// Passes the exception message and stack trace to the crash analyzer service +// for further handling. +zx_status_t HandleException(std::shared_ptr<::sys::ServiceDirectory> services, + const std::string& component_url, + const std::string& error, + const std::string& stack_trace); + +} // namespace dart_utils + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_HANDLE_EXCEPTION_H_ diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/inlines.h b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/inlines.h new file mode 100644 index 00000000000..5bd6b07d0b7 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/inlines.h @@ -0,0 +1,32 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_INLINES_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_INLINES_H_ + +#include + +namespace dart_utils { + +inline void Check(bool condition, const char* tag, const char* message = "") { + if (!condition) { + FX_LOG(FATAL, tag, message); + } +} + +#ifndef NDEBUG +#define DEBUG_CHECK(condition, tag, message) \ + dart_utils::Check(condition, tag, message) +#else +#define DEBUG_CHECK(condition, tag, message) (true || (condition)) +#endif + +template +inline size_t ArraySize(T (&array)[SIZE]) { + return SIZE; +} + +} // namespace dart_utils + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_INLINES_H_ diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/logging.h b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/logging.h new file mode 100644 index 00000000000..fdb60e94b31 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/logging.h @@ -0,0 +1,15 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_LOGGING_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_LOGGING_H_ + +namespace dart_utils { + +// Use to mark logs published via the syslog API. +#define LOG_TAG "dart-utils" + +} // namespace dart_utils + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_LOGGING_H_ diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/run_vmservice_object_tests.sh b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/run_vmservice_object_tests.sh new file mode 100644 index 00000000000..61173b8b630 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/run_vmservice_object_tests.sh @@ -0,0 +1,33 @@ +#!/boot/bin/sh +# 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. + +set -x + +# Kill any existing dart runners. +killall dart* || true + +# Start up a dart runner app that is guaranteed to be JIT, non-product, and +# won't terminate. +run -d fuchsia-pkg://fuchsia.com/hello_dart_jit#meta/hello_dart_jit.cmx + +# Wait for it to come up. +sleep 2 + +# Find the path to its vm service port. +# NB: This is the command used by the Flutter host-side command line tools. +# If the use of 'find' here breaks, the Flutter host-side command line tools +# will also be broken. If this is intentional, then craft and land a Flutter PR. +# See: https://github.com/flutter/flutter/commit/b18a2b1794606a6cddb6d7f3486557e473e3bfbb +# Then, land a hard transition to GI that updates Flutter and this test. +FIND_RESULT=`find /hub -name vmservice-port | grep dart_jit_runner` + +echo "find result:\n${FIND_RESULT}" + +killall dart* || true +if [ -z "${FIND_RESULT}" ]; then + echo "FAILURE: Dart VM service not found in the Hub!" + exit 1 +fi +exit 0 diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.cc b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.cc new file mode 100644 index 00000000000..03d14643992 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.cc @@ -0,0 +1,89 @@ +// 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 "runtime/dart/utils/tempfs.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "runtime/dart/utils/logging.h" + +namespace { + +constexpr char kTmpPath[] = "/tmp"; +[[maybe_unused]] constexpr size_t kMaxTmpPages = 1024; + +void DispatchTempMemFS() { + async::Loop loop(&kAsyncLoopConfigAttachToThread); +#if defined(DART_PRODUCT) + zx_status_t status = memfs_install_at_with_page_limit(loop.dispatcher(), + kMaxTmpPages, kTmpPath); +#else + // Hot reload uses /tmp to hold the updated dills and assets so do not + // impose any size limitation in non product runners. + zx_status_t status = memfs_install_at(loop.dispatcher(), kTmpPath); +#endif + if (status != ZX_OK) { + FX_LOGF(ERROR, LOG_TAG, "Failed to install a /tmp memfs: %s", + zx_status_get_string(status)); + return; + } + loop.Run(); +} + +} // namespace + +namespace dart_utils { + +// Set up a memfs bound to /tmp in the process-wide namespace that has the +// lifetime of the process. +void SetupRunnerTemp() { + std::thread thread(DispatchTempMemFS); + thread.detach(); +} + +void SetupComponentTemp(fdio_ns_t* ns) { + // TODO(zra): Should isolates share a /tmp file system within a process, or + // should isolates each get their own private memfs for /tmp? For now, + // sharing the process-wide /tmp simplifies hot reload since the hot reload + // devfs requires sharing between the service isolate and the app isolates. + zx_status_t status; + fdio_flat_namespace_t* rootns; + status = fdio_ns_export_root(&rootns); + if (status != ZX_OK) { + FX_LOGF(ERROR, LOG_TAG, "Failed to export root ns: %s", + zx_status_get_string(status)); + return; + } + + zx_handle_t tmp_dir_handle; + for (size_t i = 0; i < rootns->count; i++) { + if (strcmp(rootns->path[i], kTmpPath) == 0) { + tmp_dir_handle = rootns->handle[i]; + } else { + zx_handle_close(rootns->handle[i]); + rootns->handle[i] = ZX_HANDLE_INVALID; + } + } + free(rootns); + rootns = nullptr; + + status = fdio_ns_bind(ns, kTmpPath, tmp_dir_handle); + if (status != ZX_OK) { + zx_handle_close(tmp_dir_handle); + FX_LOGF(ERROR, LOG_TAG, + "Failed to bind /tmp directory into isolate namespace: %s", + zx_status_get_string(status)); + } +} + +} // namespace dart_utils diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.h b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.h new file mode 100644 index 00000000000..33b07e92a51 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.h @@ -0,0 +1,24 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_TEMPFS_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_TEMPFS_H_ + +#include + +// Utility functions that set up /tmp for the dart_runner and flutter_runner. + +namespace dart_utils { + +// Set up a memfs bound to /tmp in the process-wide namespace that has the +// lifetime of the process. +void SetupRunnerTemp(); + +// Take the memfs mapped into the process-wide namespace for /tmp, and map it to +// /tmp in the given namespace. +void SetupComponentTemp(fdio_ns_t* ns); + +} // namespace dart_utils + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_TEMPFS_H_ diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.cc b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.cc new file mode 100644 index 00000000000..130181c777b --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.cc @@ -0,0 +1,74 @@ +// 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 "runtime/dart/utils/vmo.h" + +#include +#include + +#include +#include +#include + +#include "runtime/dart/utils/logging.h" + +namespace { + +bool VmoFromFd(int fd, fuchsia::mem::Buffer* buffer) { + if (!buffer) { + FX_LOG(FATAL, LOG_TAG, "Invalid buffer pointer"); + } + + struct stat stat_struct; + if (fstat(fd, &stat_struct) == -1) { + FX_LOGF(ERROR, LOG_TAG, "fstat failed: %s", strerror(errno)); + return false; + } + + zx_handle_t result = ZX_HANDLE_INVALID; + if (fdio_get_vmo_copy(fd, &result) != ZX_OK) { + return false; + } + + buffer->vmo = zx::vmo(result); + buffer->size = stat_struct.st_size; + + return true; +} + +} // namespace + +namespace dart_utils { + +bool VmoFromFilename(const std::string& filename, + fuchsia::mem::Buffer* buffer) { + return VmoFromFilenameAt(AT_FDCWD, filename, buffer); +} + +bool VmoFromFilenameAt(int dirfd, + const std::string& filename, + fuchsia::mem::Buffer* buffer) { + int fd = openat(dirfd, filename.c_str(), O_RDONLY); + if (fd == -1) { + FX_LOGF(ERROR, LOG_TAG, "openat(\"%s\") failed: %s", filename.c_str(), + strerror(errno)); + return false; + } + bool result = VmoFromFd(fd, buffer); + close(fd); + return result; +} + +zx_status_t IsSizeValid(const fuchsia::mem::Buffer& buffer, bool* is_valid) { + size_t vmo_size; + zx_status_t status = buffer.vmo.get_size(&vmo_size); + if (status == ZX_OK) { + *is_valid = vmo_size >= buffer.size; + } else { + *is_valid = false; + } + return status; +} + +} // namespace dart_utils diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.h b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.h new file mode 100644 index 00000000000..bc4065eb815 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.h @@ -0,0 +1,24 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMO_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMO_H_ + +#include + +#include + +namespace dart_utils { + +bool VmoFromFilename(const std::string& filename, fuchsia::mem::Buffer* buffer); + +bool VmoFromFilenameAt(int dirfd, + const std::string& filename, + fuchsia::mem::Buffer* buffer); + +zx_status_t IsSizeValid(const fuchsia::mem::Buffer& buffer, bool* is_valid); + +} // namespace dart_utils + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMO_H_ diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.cc b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.cc new file mode 100644 index 00000000000..7da84b46e03 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.cc @@ -0,0 +1,63 @@ +// 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 "runtime/dart/utils/vmservice_object.h" + +#include +#include +#include + +#include +#include +#include + +#include "runtime/dart/utils/logging.h" + +namespace { + +bool ReadDirContents(const std::string& path, std::vector* out) { + out->clear(); + DIR* dir = opendir(path.c_str()); + if (!dir) { + return false; + } + struct dirent* de; + errno = 0; + while ((de = readdir(dir)) != nullptr) { + out->push_back(de->d_name); + } + closedir(dir); + return !errno; +} + +} // namespace + +namespace dart_utils { + +void VMServiceObject::GetContents(LazyEntryVector* out_vector) const { + // List /tmp/dart.services if it exists, and push its contents as + // as the conrtents of this directory. + std::vector files; + if (!ReadDirContents(kPortDir, &files)) { + FX_LOGF(ERROR, LOG_TAG, + "Failed to read Dart VM Service port directory '%s': %s", kPortDir, + strerror(errno)); + return; + } + for (const auto& file : files) { + if ((file == ".") || (file == "..")) { + continue; + } + out_vector->push_back({std::stoul(file) + GetStartingId(), file, + fuchsia::io::MODE_TYPE_FILE}); + } +} + +zx_status_t VMServiceObject::GetFile(Node** out_node, + uint64_t id, + std::string name) const { + return ZX_ERR_NOT_FOUND; +} + +} // namespace dart_utils diff --git a/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.h b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.h new file mode 100644 index 00000000000..697922491a2 --- /dev/null +++ b/engine/src/flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.h @@ -0,0 +1,26 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMSERVICE_OBJECT_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMSERVICE_OBJECT_H_ + +#include + +namespace dart_utils { + +class VMServiceObject : public vfs::LazyDir { + public: + static constexpr const char* kDirName = "DartVM"; + static constexpr const char* kPortDirName = "vmservice-port"; + static constexpr const char* kPortDir = "/tmp/dart.services"; + + void GetContents(LazyEntryVector* out_vector) const override; + zx_status_t GetFile(Node** out_node, + uint64_t id, + std::string name) const override; +}; + +} // namespace dart_utils + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMSERVICE_OBJECT_H_