[fuchsia] remove handler

* Fuchsia only uses Crashpad for minidump generation, report database
  and report upload, not for the actual exception handling so it does
  not need a handler class
* the current handler class didn't have tests anyway
* Chromium on Fuchsia relies on the platform exception handling instead
  of rolling its own Crashpad exception handler
* this avoids us having to maintain an exception handler in another repo
* this removes the last FIDL dependency in Crashpad

TESTED=`fx test crashpad_test`

Change-Id: Ie3998f709e7cc4252dd551882a23b337864da85e
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2165638
Commit-Queue: Francois Rousseau <frousseau@google.com>
Reviewed-by: Scott Graham <scottmg@chromium.org>
This commit is contained in:
Francois Rousseau 2020-04-24 14:32:54 -07:00 committed by Commit Bot
parent a519f1bec3
commit 6d8b196150
9 changed files with 6 additions and 467 deletions

View File

@ -42,10 +42,10 @@ if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
"test:test_test",
]
if (!crashpad_is_ios) {
deps += [
"handler:handler_test",
"snapshot:snapshot_test",
]
deps += [ "snapshot:snapshot_test" ]
}
if (!crashpad_is_ios && !crashpad_is_fuchsia) {
deps += [ "handler:handler_test" ]
}
if (crashpad_is_in_fuchsia) {
# TODO(fuchsia:46559): Fix the leaks and remove this.
@ -182,7 +182,7 @@ if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
"handler:handler_test",
"test:gtest_main",
]
if (crashpad_is_ios) {
if (crashpad_is_ios || crashpad_is_fuchsia) {
deps -= [ "handler:handler_test" ]
}
}

View File

@ -163,7 +163,7 @@ source_set("client_test") {
"../util",
]
if (!crashpad_is_ios) {
if (!crashpad_is_ios && !crashpad_is_fuchsia) {
data_deps = [ "../handler:crashpad_handler" ]
}

View File

@ -65,15 +65,6 @@ static_library("handler") {
]
}
if (crashpad_is_fuchsia) {
sources += [
"fuchsia/crash_report_exception_handler.cc",
"fuchsia/crash_report_exception_handler.h",
"fuchsia/exception_handler_server.cc",
"fuchsia/exception_handler_server.h",
]
}
public_configs = [ "..:crashpad_config" ]
public_deps = [
@ -91,10 +82,6 @@ static_library("handler") {
if (crashpad_is_win) {
cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union
}
if (crashpad_is_fuchsia) {
deps += [ "../third_party/fuchsia" ]
}
}
if (crashpad_is_android) {

View File

@ -1,151 +0,0 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "handler/fuchsia/crash_report_exception_handler.h"
#include <lib/zx/thread.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls/exception.h>
#include "base/fuchsia/fuchsia_logging.h"
#include "client/settings.h"
#include "minidump/minidump_file_writer.h"
#include "minidump/minidump_user_extension_stream_data_source.h"
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
#include "util/fuchsia/koid_utilities.h"
#include "util/fuchsia/scoped_task_suspend.h"
namespace crashpad {
CrashReportExceptionHandler::CrashReportExceptionHandler(
CrashReportDatabase* database,
CrashReportUploadThread* upload_thread,
const std::map<std::string, std::string>* process_annotations,
const std::map<std::string, fuchsia::mem::Buffer>* process_attachments,
const UserStreamDataSources* user_stream_data_sources)
: database_(database),
upload_thread_(upload_thread),
process_annotations_(process_annotations),
process_attachments_(process_attachments),
user_stream_data_sources_(user_stream_data_sources) {}
CrashReportExceptionHandler::~CrashReportExceptionHandler() {}
bool CrashReportExceptionHandler::HandleException(const zx::process& process,
const zx::thread& thread,
UUID* local_report_id) {
ScopedTaskSuspend suspend(process);
ProcessSnapshotFuchsia process_snapshot;
if (!process_snapshot.Initialize(process)) {
return false;
}
CrashpadInfoClientOptions client_options;
process_snapshot.GetCrashpadOptions(&client_options);
if (client_options.crashpad_handler_behavior == TriState::kDisabled) {
return true;
}
zx_exception_report_t report;
zx_status_t status = thread.get_info(ZX_INFO_THREAD_EXCEPTION_REPORT,
&report,
sizeof(report),
nullptr,
nullptr);
if (status != ZX_OK) {
ZX_LOG(ERROR, status)
<< "zx_object_get_info ZX_INFO_THREAD_EXCEPTION_REPORT";
return false;
}
zx_koid_t thread_id = GetKoidForHandle(thread);
if (!process_snapshot.InitializeException(thread_id, report)) {
return false;
}
UUID client_id;
Settings* const settings = database_->GetSettings();
if (settings) {
// If GetSettings() or GetClientID() fails, something else will log a
// message and client_id will be left at its default value, all zeroes,
// which is appropriate.
settings->GetClientID(&client_id);
}
process_snapshot.SetClientID(client_id);
process_snapshot.SetAnnotationsSimpleMap(*process_annotations_);
std::unique_ptr<CrashReportDatabase::NewReport> new_report;
CrashReportDatabase::OperationStatus database_status =
database_->PrepareNewCrashReport(&new_report);
if (database_status != CrashReportDatabase::kNoError) {
return false;
}
process_snapshot.SetReportID(new_report->ReportID());
MinidumpFileWriter minidump;
minidump.InitializeFromSnapshot(&process_snapshot);
AddUserExtensionStreams(
user_stream_data_sources_, &process_snapshot, &minidump);
if (!minidump.WriteEverything(new_report->Writer())) {
return false;
}
if (process_attachments_) {
// Note that attachments are read at this point each time rather than once
// so that if the contents of the VMO has changed it will be re-read for
// each upload (e.g. in the case of a log file).
for (const auto& it : *process_attachments_) {
// TODO(frousseau): make FileWriter VMO-aware.
FileWriter* writer = new_report->AddAttachment(it.first);
if (!writer) {
continue;
}
auto data = std::make_unique<uint8_t[]>(it.second.size);
const zx_status_t read_status =
it.second.vmo.read(data.get(), 0u, it.second.size);
if (read_status != ZX_OK) {
ZX_LOG(ERROR, read_status)
<< "could not read VMO for attachment " << it.first;
// Not being able to read the VMO isn't considered fatal, and
// should not prevent the report from being processed.
continue;
}
writer->Write(data.get(), it.second.size);
}
}
UUID uuid;
database_status =
database_->FinishedWritingCrashReport(std::move(new_report), &uuid);
if (database_status != CrashReportDatabase::kNoError) {
return false;
}
if (local_report_id != nullptr) {
*local_report_id = uuid;
}
if (upload_thread_) {
upload_thread_->ReportPending(uuid);
}
return true;
}
} // namespace crashpad

View File

@ -1,100 +0,0 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_
#define CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_
#include <fuchsia/mem/cpp/fidl.h>
#include <lib/zx/port.h>
#include <lib/zx/process.h>
#include <lib/zx/thread.h>
#include <stdint.h>
#include <zircon/types.h>
#include <map>
#include <string>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "client/crash_report_database.h"
#include "handler/crash_report_upload_thread.h"
#include "handler/user_stream_data_source.h"
#include "util/misc/uuid.h"
namespace crashpad {
//! \brief An exception handler that writes crash reports for exception messages
//! to a CrashReportDatabase.
class CrashReportExceptionHandler {
public:
//! \brief Creates a new object that will store crash reports in \a database.
//!
//! \param[in] database The database to store crash reports in. Weak.
//! \param[in] upload_thread The upload thread to notify when a new crash
//! report is written into \a database.
//! \param[in] process_annotations A map of annotations to insert as
//! process-level annotations into each crash report that is written. Do
//! not confuse this with module-level annotations, which are under the
//! control of the crashing process, and are used to implement Chrome's
//! "crash keys." Process-level annotations are those that are beyond the
//! control of the crashing process, which must reliably be set even if
//! the process crashes before its able to establish its own annotations.
//! To interoperate with Breakpad servers, the recommended practice is to
//! specify values for the `"prod"` and `"ver"` keys as process
//! annotations.
//! \param[in] process_attachments A map of keys to VMOs to be included in the
//! report. Each time a report is written, the VMOs will be read in their
//! entirety and included in the report using the key as the name in the
//! http upload.
//! \param[in] user_stream_data_sources Data sources to be used to extend
//! crash reports. For each crash report that is written, the data sources
//! are called in turn. These data sources may contribute additional
//! minidump streams. `nullptr` if not required.
CrashReportExceptionHandler(
CrashReportDatabase* database,
CrashReportUploadThread* upload_thread,
const std::map<std::string, std::string>* process_annotations,
const std::map<std::string, fuchsia::mem::Buffer>* process_attachments,
const UserStreamDataSources* user_stream_data_sources);
~CrashReportExceptionHandler();
//! \brief Called when the exception handler server has caught an exception
//! and wants a crash dump to be taken.
//!
//! \param[in] process The handle to the process which sustained the
//! exception.
//! \param[in] thread The handle to the thread of \a process which sustained
//! the exception.
//! \param[out] local_report_id The unique identifier for the report created
//! in the local report database. Optional.
//! \return `true` on success, or `false` with an error logged.
bool HandleException(const zx::process& process,
const zx::thread& thread,
UUID* local_report_id = nullptr);
private:
CrashReportDatabase* database_; // weak
CrashReportUploadThread* upload_thread_; // weak
const std::map<std::string, std::string>* process_annotations_; // weak
const std::map<std::string, fuchsia::mem::Buffer>*
process_attachments_; // weak
const UserStreamDataSources* user_stream_data_sources_; // weak
DISALLOW_COPY_AND_ASSIGN(CrashReportExceptionHandler);
};
} // namespace crashpad
#endif // CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_

View File

@ -1,89 +0,0 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "handler/fuchsia/exception_handler_server.h"
#include <lib/zx/exception.h>
#include <lib/zx/time.h>
#include <zircon/syscalls/exception.h>
#include <utility>
#include "base/fuchsia/fuchsia_logging.h"
#include "base/logging.h"
#include "handler/fuchsia/crash_report_exception_handler.h"
namespace crashpad {
ExceptionHandlerServer::ExceptionHandlerServer(zx::job root_job,
zx::channel exception_channel)
: root_job_(std::move(root_job)),
exception_channel_(std::move(exception_channel)) {}
ExceptionHandlerServer::~ExceptionHandlerServer() = default;
void ExceptionHandlerServer::Run(CrashReportExceptionHandler* handler) {
while (true) {
zx_signals_t signals;
zx_status_t status = exception_channel_.wait_one(
ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED,
zx::time::infinite(),
&signals);
if (status != ZX_OK) {
ZX_LOG(ERROR, status) << "zx_port_wait, aborting";
return;
}
if (signals & ZX_CHANNEL_READABLE) {
zx_exception_info_t info;
zx::exception exception;
status = exception_channel_.read(0,
&info,
exception.reset_and_get_address(),
sizeof(info),
1,
nullptr,
nullptr);
if (status != ZX_OK) {
ZX_LOG(ERROR, status) << "zx_channel_read, aborting";
return;
}
zx::process process;
status = exception.get_process(&process);
if (status != ZX_OK) {
ZX_LOG(ERROR, status) << "zx_exception_get_process, aborting";
return;
}
zx::thread thread;
status = exception.get_thread(&thread);
if (status != ZX_OK) {
ZX_LOG(ERROR, status) << "zx_exception_get_thread, aborting";
return;
}
bool result =
handler->HandleException(std::move(process), std::move(thread));
if (!result) {
LOG(ERROR) << "HandleException failed";
}
} else {
// Job terminated, exit the loop.
return;
}
}
}
} // namespace crashpad

View File

@ -1,56 +0,0 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_FUCHSIA_EXCEPTION_HANDLER_SERVER_H_
#define CRASHPAD_HANDLER_FUCHSIA_EXCEPTION_HANDLER_SERVER_H_
#include <lib/zx/channel.h>
#include <lib/zx/job.h>
#include "base/macros.h"
namespace crashpad {
class CrashReportExceptionHandler;
//! \brief Runs the main exception-handling server in Crashpad's handler
//! process.
class ExceptionHandlerServer {
public:
//! \brief Constructs an ExceptionHandlerServer object.
//!
//! \param[in] root_job The root of the tree of processes that will be handled
//! by this server. It is assumed that \a exception_channel is the
// exception channel of this job.
//! \param[in] exception_channel The exception channel that this server will
//! monitor.
ExceptionHandlerServer(zx::job root_job, zx::channel exception_channel);
~ExceptionHandlerServer();
//! \brief Runs the exception-handling server.
//!
//! \param[in] handler The handler to which the exceptions are delegated when
//! they are caught in Run(). Ownership is not transferred.
void Run(CrashReportExceptionHandler* handler);
private:
zx::job root_job_;
zx::channel exception_channel_;
DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerServer);
};
} // namespace crashpad
#endif // CRASHPAD_HANDLER_FUCHSIA_EXCEPTION_HANDLER_SERVER_H_

View File

@ -86,15 +86,6 @@
#include "util/win/handle.h"
#include "util/win/initial_client_data.h"
#include "util/win/session_end_watcher.h"
#elif defined(OS_FUCHSIA)
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <lib/zx/channel.h>
#include <lib/zx/job.h>
#include "handler/fuchsia/crash_report_exception_handler.h"
#include "handler/fuchsia/exception_handler_server.h"
#elif defined(OS_LINUX)
#include "handler/linux/crash_report_exception_handler.h"
#include "handler/linux/exception_handler_server.h"
@ -420,22 +411,6 @@ void InstallCrashHandler() {
ALLOW_UNUSED_LOCAL(terminate_handler);
}
#elif defined(OS_FUCHSIA)
void InstallCrashHandler() {
// There's nothing to do here. Crashes in this process will already be caught
// here because this handler process is in the same job that has had its
// exception port bound.
// TODO(scottmg): This should collect metrics on handler crashes, at a
// minimum. https://crashpad.chromium.org/bug/230.
}
void ReinstallCrashHandler() {
// TODO(scottmg): Fuchsia: https://crashpad.chromium.org/bug/196
NOTREACHED();
}
#endif // OS_MACOSX
void MonitorSelf(const Options& options) {
@ -1013,10 +988,6 @@ int HandlerMain(int argc,
database.get(),
static_cast<CrashReportUploadThread*>(upload_thread.Get()),
&options.annotations,
#if defined(OS_FUCHSIA)
// TODO(scottmg): Process level file attachments, and for all platforms.
nullptr,
#endif
#if defined(OS_ANDROID)
options.write_minidump_to_database,
options.write_minidump_to_log,
@ -1100,26 +1071,6 @@ int HandlerMain(int argc,
if (!options.pipe_name.empty()) {
exception_handler_server.SetPipeName(base::UTF8ToUTF16(options.pipe_name));
}
#elif defined(OS_FUCHSIA)
// These handles are logically "moved" into these variables when retrieved by
// zx_take_startup_handle(). Both are given to ExceptionHandlerServer which
// owns them in this process. There is currently no "connect-later" mode on
// Fuchsia, all the binding must be done by the client before starting
// crashpad_handler.
zx::job root_job(zx_take_startup_handle(PA_HND(PA_USER0, 0)));
if (!root_job.is_valid()) {
LOG(ERROR) << "no job handle passed in startup handle 0";
return EXIT_FAILURE;
}
zx::channel exception_channel(zx_take_startup_handle(PA_HND(PA_USER0, 1)));
if (!exception_channel.is_valid()) {
LOG(ERROR) << "no exception channel handle passed in startup handle 1";
return EXIT_FAILURE;
}
ExceptionHandlerServer exception_handler_server(std::move(root_job),
std::move(exception_channel));
#elif defined(OS_LINUX) || defined(OS_ANDROID)
ExceptionHandlerServer exception_handler_server;
#endif // OS_MACOSX

View File

@ -19,13 +19,11 @@ if (crashpad_is_in_fuchsia) {
public_deps = [
"//zircon/public/lib/fdio",
"//zircon/public/lib/zx",
"//zircon/system/fidl/fuchsia-mem",
]
}
} else if (crashpad_is_in_chromium) {
group("fuchsia") {
public_deps = [
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mem",
"//third_party/fuchsia-sdk/sdk/pkg/fdio",
"//third_party/fuchsia-sdk/sdk/pkg/zx",
]
@ -33,7 +31,6 @@ if (crashpad_is_in_fuchsia) {
} else {
group("fuchsia") {
public_deps = [
"//third_party/fuchsia/sdk/$host_os-amd64/fidl/fuchsia.mem",
"//third_party/fuchsia/sdk/$host_os-amd64/pkg/fdio",
"//third_party/fuchsia/sdk/$host_os-amd64/pkg/zx",
]