mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
This implementation has some limitations as documented in the header, however, threads must be suspended in order to use the register capture debug API so this is somewhat useful for now in the context of generate_dump. Also, refactor some child-object retrieval helpers used in a few places. Bug: crashpad:196 Change-Id: I1fdae5fc3d4b43841e535724eac10c1e58af04c5 Reviewed-on: https://chromium-review.googlesource.com/1007966 Commit-Queue: Scott Graham <scottmg@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
92 lines
2.6 KiB
C++
92 lines
2.6 KiB
C++
// Copyright 2018 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 "util/fuchsia/scoped_task_suspend.h"
|
|
|
|
#include <zircon/process.h>
|
|
#include <zircon/syscalls.h>
|
|
|
|
#include <vector>
|
|
|
|
#include "base/fuchsia/fuchsia_logging.h"
|
|
#include "base/fuchsia/scoped_zx_handle.h"
|
|
#include "base/logging.h"
|
|
#include "util/fuchsia/koid_utilities.h"
|
|
|
|
namespace crashpad {
|
|
|
|
namespace {
|
|
|
|
zx_obj_type_t GetHandleType(zx_handle_t handle) {
|
|
zx_info_handle_basic_t basic;
|
|
zx_status_t status = zx_object_get_info(
|
|
handle, ZX_INFO_HANDLE_BASIC, &basic, sizeof(basic), nullptr, nullptr);
|
|
if (status != ZX_OK) {
|
|
ZX_LOG(ERROR, status) << "zx_object_get_info";
|
|
return ZX_OBJ_TYPE_NONE;
|
|
}
|
|
return basic.type;
|
|
}
|
|
|
|
bool SuspendThread(zx_handle_t thread) {
|
|
zx_status_t status = zx_task_suspend(thread);
|
|
ZX_LOG_IF(ERROR, status != ZX_OK, status) << "zx_task_suspend";
|
|
return status == ZX_OK;
|
|
}
|
|
|
|
bool ResumeThread(zx_handle_t thread) {
|
|
zx_status_t status = zx_task_resume(thread, 0);
|
|
ZX_LOG_IF(ERROR, status != ZX_OK, status) << "zx_task_resume";
|
|
return status == ZX_OK;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
ScopedTaskSuspend::ScopedTaskSuspend(zx_handle_t task) : task_(task) {
|
|
DCHECK_NE(task_, zx_process_self());
|
|
DCHECK_NE(task_, zx_thread_self());
|
|
|
|
zx_obj_type_t type = GetHandleType(task_);
|
|
if (type == ZX_OBJ_TYPE_THREAD) {
|
|
if (!SuspendThread(task_)) {
|
|
task_ = ZX_HANDLE_INVALID;
|
|
}
|
|
} else if (type == ZX_OBJ_TYPE_PROCESS) {
|
|
for (const auto& thread : GetChildHandles(task_, ZX_INFO_PROCESS_THREADS)) {
|
|
SuspendThread(thread.get());
|
|
}
|
|
} else {
|
|
LOG(ERROR) << "unexpected handle type";
|
|
task_ = ZX_HANDLE_INVALID;
|
|
}
|
|
}
|
|
|
|
ScopedTaskSuspend::~ScopedTaskSuspend() {
|
|
if (task_ != ZX_HANDLE_INVALID) {
|
|
zx_obj_type_t type = GetHandleType(task_);
|
|
if (type == ZX_OBJ_TYPE_THREAD) {
|
|
ResumeThread(task_);
|
|
} else if (type == ZX_OBJ_TYPE_PROCESS) {
|
|
for (const auto& thread :
|
|
GetChildHandles(task_, ZX_INFO_PROCESS_THREADS)) {
|
|
ResumeThread(thread.get());
|
|
}
|
|
} else {
|
|
LOG(ERROR) << "unexpected handle type";
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace crashpad
|