[ios] Add optional UploadBehavior enum to InProcessHandler::StartProcessingPendingReports()

Previously, StartProcessingPendingReports() only started the prune and
upload threads if it thought the application was actively running in
the foreground.

However, some Crashpad clients would like to replicate Breakpad's
behavior of allowing uploads while the application is starting up
(before it moves to the foreground).

This CL introdues an optional UploadBehavior enum to
InProcessHandler::StartProcessingPendingReports(), defaulting to the
current behavior of only uploading processed crash reports while the
application is in the foreground.

If the enum is set to UploadBehavior::kUploadImmediately, then
InProcessHandler will start the prune and upload threads regardless
of the application state. (If the application state later transitions
to a non-active state, then InProcessHandler will stop the prune and
upload threads as normal.)

Change-Id: I4f13f3a3006d636dd3e511b21ccc23a90b2ea639
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3894230
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Justin Cohen <justincohen@chromium.org>
Reviewed-by: Justin Cohen <justincohen@chromium.org>
This commit is contained in:
Ben Hamilton 2022-09-15 13:14:19 -06:00 committed by Crashpad LUCI CQ
parent 9f472e5a18
commit 833219f1ad
6 changed files with 82 additions and 13 deletions

View File

@ -42,6 +42,7 @@ crashpad_static_library("client") {
"ios_handler/prune_intermediate_dumps_and_crash_reports_thread.cc",
"ios_handler/prune_intermediate_dumps_and_crash_reports_thread.h",
"simulate_crash_ios.h",
"upload_behavior_ios.h",
]
}

View File

@ -39,6 +39,10 @@
#include <ucontext.h>
#endif
#if BUILDFLAG(IS_IOS)
#include "client/upload_behavior_ios.h"
#endif
namespace crashpad {
//! \brief The primary interface for an application to have Crashpad monitor
@ -531,7 +535,12 @@ class CrashpadClient {
//! on another thread. This method does not block.
//!
//! A handler must have already been installed before calling this method.
static void StartProcessingPendingReports();
//!
//! \param[in] upload_behavior Controls when the upload thread will run and
//! process pending reports. By default, only uploads pending reports
//! when the application is active.
static void StartProcessingPendingReports(
UploadBehavior upload_behavior = UploadBehavior::kUploadWhenAppIsActive);
//! \brief Requests that the handler capture an intermediate dump even though
//! there hasn't been a crash. The intermediate dump will be converted

View File

@ -148,9 +148,9 @@ class CrashHandler : public Thread,
context, kMachExceptionSimulated, path);
}
void StartProcessingPendingReports() {
void StartProcessingPendingReports(UploadBehavior upload_behavior) {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
in_process_handler_.StartProcessingPendingReports();
in_process_handler_.StartProcessingPendingReports(upload_behavior);
}
void SetMachExceptionCallbackForTesting(void (*callback)()) {
@ -439,10 +439,11 @@ void CrashpadClient::ProcessIntermediateDump(
}
// static
void CrashpadClient::StartProcessingPendingReports() {
void CrashpadClient::StartProcessingPendingReports(
UploadBehavior upload_behavior) {
CrashHandler* crash_handler = CrashHandler::Get();
DCHECK(crash_handler);
crash_handler->StartProcessingPendingReports();
crash_handler->StartProcessingPendingReports(upload_behavior);
}
// static

View File

@ -65,7 +65,7 @@ InProcessHandler::~InProcessHandler() {
if (cached_writer_) {
cached_writer_->Close();
}
UpdatePruneAndUploadThreads(false);
UpdatePruneAndUploadThreads(false, UploadBehavior::kUploadWhenAppIsActive);
}
bool InProcessHandler::Initialize(
@ -118,7 +118,8 @@ bool InProcessHandler::Initialize(
system_data_.SetActiveApplicationCallback([this](bool active) {
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UpdatePruneAndUploadThreads(active);
UpdatePruneAndUploadThreads(active,
UploadBehavior::kUploadWhenAppIsActive);
});
});
}
@ -272,7 +273,8 @@ void InProcessHandler::ProcessIntermediateDump(
}
}
void InProcessHandler::StartProcessingPendingReports() {
void InProcessHandler::StartProcessingPendingReports(
UploadBehavior upload_behavior) {
if (!upload_thread_)
return;
@ -284,15 +286,27 @@ void InProcessHandler::StartProcessingPendingReports() {
// TODO(crbug.com/crashpad/400): Consider moving prune and upload thread to
// BackgroundTasks and/or NSURLSession. This might allow uploads to continue
// in the background.
UpdatePruneAndUploadThreads(system_data_.IsApplicationActive());
UpdatePruneAndUploadThreads(system_data_.IsApplicationActive(),
upload_behavior);
}
void InProcessHandler::UpdatePruneAndUploadThreads(bool active) {
void InProcessHandler::UpdatePruneAndUploadThreads(
bool active,
UploadBehavior upload_behavior) {
base::AutoLock lock_owner(prune_and_upload_lock_);
// TODO(crbug.com/crashpad/400): Consider moving prune and upload thread to
// BackgroundTasks and/or NSURLSession. This might allow uploads to continue
// in the background.
if (active) {
bool threads_should_run;
switch (upload_behavior) {
case UploadBehavior::kUploadWhenAppIsActive:
threads_should_run = active;
break;
case UploadBehavior::kUploadImmediately:
threads_should_run = true;
break;
}
if (threads_should_run) {
if (!prune_thread_->is_running())
prune_thread_->Start();
if (upload_thread_enabled_ && !upload_thread_->is_running()) {

View File

@ -24,6 +24,7 @@
#include "base/files/file_path.h"
#include "base/synchronization/lock.h"
#include "client/ios_handler/prune_intermediate_dumps_and_crash_reports_thread.h"
#include "client/upload_behavior_ios.h"
#include "handler/crash_report_upload_thread.h"
#include "snapshot/ios/process_snapshot_ios_intermediate_dump.h"
#include "util/ios/ios_intermediate_dump_writer.h"
@ -172,7 +173,12 @@ class InProcessHandler {
//! \brief Requests that the handler begin in-process uploading of any
//! pending reports.
void StartProcessingPendingReports();
//!
//! \param[in] upload_behavior Controls when the upload thread will run and
//! process pending reports. By default, only uploads pending reports
//! when the application is active.
void StartProcessingPendingReports(
UploadBehavior upload_behavior = UploadBehavior::kUploadWhenAppIsActive);
//! \brief Inject a callback into Mach handling. Intended to be used by
//! tests to trigger a reentrant exception.
@ -224,7 +230,12 @@ class InProcessHandler {
};
//! \brief Manage the prune and upload thread when the active state changes.
void UpdatePruneAndUploadThreads(bool active);
//!
//! \param[in] active `true` if the application is actively running in the
//! foreground, `false` otherwise.
//! \param[in] upload_behavior Controls when the upload thread will run and
//! process pending reports.
void UpdatePruneAndUploadThreads(bool active, UploadBehavior upload_behavior);
//! \brief Writes a minidump to the Crashpad database from the
//! \a process_snapshot, and triggers the upload_thread_ if started.

View File

@ -0,0 +1,33 @@
// Copyright 2022 The Crashpad Authors
//
// 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_CLIENT_UPLOAD_BEHAVIOR_IOS_H_
#define CRASHPAD_CLIENT_UPLOAD_BEHAVIOR_IOS_H_
namespace crashpad {
//! \brief Enum to control upload behavior when processing pending reports.
enum class UploadBehavior {
//! \brief Only upload reports while the application is active (e.g., in the
//! foreground).
kUploadWhenAppIsActive = 1,
//! \brief Upload reports immediately, regardless of whether or not the
//! application is active.
kUploadImmediately = 2,
};
} // namespace crashpad
#endif // CRASHPAD_CLIENT_UPLOAD_BEHAVIOR_IOS_H_