| // Copyright 2020 The Chromium OS 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 "crash-reporter/arcvm_cxx_collector.h" |
| |
| #include <utility> |
| |
| #include <base/files/file.h> |
| #include <base/files/file_path.h> |
| #include <base/files/file_util.h> |
| #include <base/strings/stringprintf.h> |
| #include <brillo/syslog_logging.h> |
| |
| #include "crash-reporter/arc_util.h" |
| #include "crash-reporter/constants.h" |
| #include "crash-reporter/util.h" |
| |
| namespace { |
| |
| // TODO(b/169638371): Remove the word "native". |
| constexpr char kArcvmCxxCollectorName[] = "ARCVM_native"; |
| |
| // "native_crash" is a tag defined in Android. |
| constexpr char kArcvmNativeCrashType[] = "native_crash"; |
| |
| } // namespace |
| |
| ArcvmCxxCollector::ArcvmCxxCollector() |
| : CrashCollector(kArcvmCxxCollectorName, |
| kAlwaysUseUserCrashDirectory, |
| kNormalCrashSendMode) {} |
| |
| ArcvmCxxCollector::~ArcvmCxxCollector() = default; |
| |
| bool ArcvmCxxCollector::HandleCrash( |
| const arc_util::BuildProperty& build_property, |
| const CrashInfo& crash_info, |
| base::TimeDelta uptime) { |
| return HandleCrashWithMinidumpFD(build_property, crash_info, uptime, |
| base::ScopedFD(STDIN_FILENO)); |
| } |
| |
| bool ArcvmCxxCollector::HandleCrashWithMinidumpFD( |
| const arc_util::BuildProperty& build_property, |
| const CrashInfo& crash_info, |
| base::TimeDelta uptime, |
| base::ScopedFD minidump_fd) { |
| const std::string message = |
| "Received crash notification for " + crash_info.exec_name; |
| LogCrash(message, "handling"); |
| |
| bool out_of_capacity = false; |
| base::FilePath crash_dir; |
| if (!GetCreatedCrashDirectoryByEuid(geteuid(), &crash_dir, |
| &out_of_capacity)) { |
| LOG(ERROR) << "Failed to create or find crash directory"; |
| if (!out_of_capacity) |
| EnqueueCollectionErrorLog(kErrorSystemIssue, crash_info.exec_name); |
| return false; |
| } |
| |
| AddArcMetadata(build_property, crash_info, uptime); |
| |
| const std::string basename_without_ext = |
| FormatDumpBasename(crash_info.exec_name, crash_info.time, crash_info.pid); |
| const base::FilePath minidump_path = GetCrashPath( |
| crash_dir, basename_without_ext, constants::kMinidumpExtension); |
| if (!DumpFdToFile(std::move(minidump_fd), minidump_path)) { |
| LOG(ERROR) << "Failed to write minidump file"; |
| return false; |
| } |
| |
| const base::FilePath metadata_path = |
| GetCrashPath(crash_dir, basename_without_ext, "meta"); |
| FinishCrash(metadata_path, crash_info.exec_name, |
| minidump_path.BaseName().value()); |
| |
| return true; |
| } |
| |
| void ArcvmCxxCollector::AddArcMetadata( |
| const arc_util::BuildProperty& build_property, |
| const CrashInfo& crash_info, |
| base::TimeDelta uptime) { |
| for (const auto& metadata : arc_util::ListBasicARCRelatedMetadata( |
| crash_info.exec_name, kArcvmNativeCrashType)) { |
| AddCrashMetaUploadData(metadata.first, metadata.second); |
| } |
| AddCrashMetaUploadData(arc_util::kChromeOsVersionField, GetOsVersion()); |
| |
| for (auto metadata : arc_util::ListMetadataForBuildProperty(build_property)) { |
| AddCrashMetaUploadData(metadata.first, metadata.second); |
| } |
| |
| if (!uptime.is_zero()) { |
| AddCrashMetaUploadData(arc_util::kUptimeField, |
| arc_util::FormatDuration(uptime)); |
| } |
| } |
| |
| bool ArcvmCxxCollector::DumpFdToFile(base::ScopedFD src_fd, |
| const base::FilePath& dst_path) { |
| base::ScopedFD dst_fd = GetNewFileHandle(dst_path); |
| if (!dst_fd.is_valid()) |
| return false; |
| |
| base::File src_file(src_fd.release()); |
| constexpr size_t kBufferSize = 4096; |
| char buffer[kBufferSize]; |
| |
| while (true) { |
| ssize_t bytes_written = |
| src_file.ReadAtCurrentPosNoBestEffort(buffer, kBufferSize); |
| if (bytes_written < 0) |
| return false; |
| if (bytes_written == 0) |
| return true; |
| if (!base::WriteFileDescriptor(dst_fd.get(), |
| base::StringPiece(buffer, bytes_written))) |
| return false; |
| } |
| } |
| |
| std::string ArcvmCxxCollector::GetProductVersion() const { |
| return arc_util::GetProductVersion(); |
| } |