ios: Support UserStreamDataSources on iOS.

Adds a parameter to the iOS ProcessIntermediateDumps API to allow for
post-crash user stream processing. Also moves user_stream_data_source.h
to handler:common to avoid a dependency cycle on iOS.

This will be used by gwp-asan.

Change-Id: Ic528725276e3c4d284aef89a86cc86878a7af9b0
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/6340388
Reviewed-by: Joshua Peraza <jperaza@chromium.org>
Commit-Queue: Justin Cohen <justincohen@chromium.org>
This commit is contained in:
Justin Cohen 2025-03-12 15:47:55 -04:00 committed by Crashpad LUCI CQ
parent 04b11f9964
commit e09f5ee484
6 changed files with 57 additions and 21 deletions

View File

@ -43,6 +43,7 @@
#if BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_IOS)
#include "client/upload_behavior_ios.h" #include "client/upload_behavior_ios.h"
#include "handler/user_stream_data_source.h" // nogncheck
#endif #endif
namespace crashpad { namespace crashpad {
@ -531,8 +532,13 @@ class CrashpadClient {
//! \param[in] annotations Process annotations to set in each crash report. //! \param[in] annotations Process annotations to set in each crash report.
//! Useful when adding crash annotations detected on the next run after a //! Useful when adding crash annotations detected on the next run after a
//! crash but before upload. //! crash but before upload.
//! \param[in] user_stream_sources An optional vector containing the
//! extensibility data sources to call on crash. Each time a minidump is
//! created, the sources are called in turn. Any streams returned are
//! added to the minidump.
static void ProcessIntermediateDumps( static void ProcessIntermediateDumps(
const std::map<std::string, std::string>& annotations = {}); const std::map<std::string, std::string>& annotations = {},
const UserStreamDataSources* user_stream_sources = {});
//! \brief Requests that the handler convert a single intermediate dump at \a //! \brief Requests that the handler convert a single intermediate dump at \a
//! file generated by DumpWithoutCrashAndDeferProcessingAtPath into a //! file generated by DumpWithoutCrashAndDeferProcessingAtPath into a

View File

@ -153,8 +153,10 @@ class CrashHandler : public Thread,
} }
void ProcessIntermediateDumps( void ProcessIntermediateDumps(
const std::map<std::string, std::string>& annotations) { const std::map<std::string, std::string>& annotations,
in_process_handler_.ProcessIntermediateDumps(annotations); const UserStreamDataSources* user_stream_sources) {
in_process_handler_.ProcessIntermediateDumps(annotations,
user_stream_sources);
} }
void ProcessIntermediateDump( void ProcessIntermediateDump(
@ -457,10 +459,11 @@ bool CrashpadClient::StartCrashpadInProcessHandler(
// static // static
void CrashpadClient::ProcessIntermediateDumps( void CrashpadClient::ProcessIntermediateDumps(
const std::map<std::string, std::string>& annotations) { const std::map<std::string, std::string>& annotations,
const UserStreamDataSources* user_stream_sources) {
CrashHandler* crash_handler = CrashHandler::Get(); CrashHandler* crash_handler = CrashHandler::Get();
DCHECK(crash_handler); DCHECK(crash_handler);
crash_handler->ProcessIntermediateDumps(annotations); crash_handler->ProcessIntermediateDumps(annotations, user_stream_sources);
} }
// static // static

View File

@ -254,21 +254,23 @@ bool InProcessHandler::MoveIntermediateDumpAtPathToPending(
return MoveFileOrDirectory(path, new_path_unlocked); return MoveFileOrDirectory(path, new_path_unlocked);
} }
void InProcessHandler::ProcessIntermediateDumps( void InProcessHandler::ProcessIntermediateDumps(
const std::map<std::string, std::string>& annotations) { const std::map<std::string, std::string>& annotations,
const UserStreamDataSources* user_stream_sources) {
INITIALIZATION_STATE_DCHECK_VALID(initialized_); INITIALIZATION_STATE_DCHECK_VALID(initialized_);
for (auto& file : PendingFiles()) for (auto& file : PendingFiles())
ProcessIntermediateDump(file, annotations); ProcessIntermediateDump(file, annotations, user_stream_sources);
} }
void InProcessHandler::ProcessIntermediateDump( void InProcessHandler::ProcessIntermediateDump(
const base::FilePath& file, const base::FilePath& file,
const std::map<std::string, std::string>& annotations) { const std::map<std::string, std::string>& annotations,
const UserStreamDataSources* user_stream_sources) {
INITIALIZATION_STATE_DCHECK_VALID(initialized_); INITIALIZATION_STATE_DCHECK_VALID(initialized_);
ProcessSnapshotIOSIntermediateDump process_snapshot; ProcessSnapshotIOSIntermediateDump process_snapshot;
if (process_snapshot.InitializeWithFilePath(file, annotations)) { if (process_snapshot.InitializeWithFilePath(file, annotations)) {
SaveSnapshot(process_snapshot); SaveSnapshot(process_snapshot, user_stream_sources);
} }
} }
@ -320,7 +322,8 @@ void InProcessHandler::UpdatePruneAndUploadThreads(
} }
void InProcessHandler::SaveSnapshot( void InProcessHandler::SaveSnapshot(
ProcessSnapshotIOSIntermediateDump& process_snapshot) { ProcessSnapshotIOSIntermediateDump& process_snapshot,
const UserStreamDataSources* user_stream_sources) {
std::unique_ptr<CrashReportDatabase::NewReport> new_report; std::unique_ptr<CrashReportDatabase::NewReport> new_report;
CrashReportDatabase::OperationStatus database_status = CrashReportDatabase::OperationStatus database_status =
database_->PrepareNewCrashReport(&new_report); database_->PrepareNewCrashReport(&new_report);
@ -339,6 +342,8 @@ void InProcessHandler::SaveSnapshot(
MinidumpFileWriter minidump; MinidumpFileWriter minidump;
minidump.InitializeFromSnapshot(&process_snapshot); minidump.InitializeFromSnapshot(&process_snapshot);
AddUserExtensionStreams(user_stream_sources, &process_snapshot, &minidump);
if (!minidump.WriteEverything(new_report->Writer())) { if (!minidump.WriteEverything(new_report->Writer())) {
Metrics::ExceptionCaptureResult( Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kMinidumpWriteFailed); Metrics::CaptureResult::kMinidumpWriteFailed);

View File

@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef CRASHPAD_CLIENT_IOS_HANDLER_IN_PROCESS_IN_PROCESS_HANDLER_H_
#define CRASHPAD_CLIENT_IOS_HANDLER_IN_PROCESS_IN_PROCESS_HANDLER_H_
#include <mach/mach.h> #include <mach/mach.h>
#include <stdint.h> #include <stdint.h>
@ -26,6 +29,7 @@
#include "client/ios_handler/prune_intermediate_dumps_and_crash_reports_thread.h" #include "client/ios_handler/prune_intermediate_dumps_and_crash_reports_thread.h"
#include "client/upload_behavior_ios.h" #include "client/upload_behavior_ios.h"
#include "handler/crash_report_upload_thread.h" #include "handler/crash_report_upload_thread.h"
#include "handler/user_stream_data_source.h"
#include "snapshot/ios/process_snapshot_ios_intermediate_dump.h" #include "snapshot/ios/process_snapshot_ios_intermediate_dump.h"
#include "util/ios/ios_intermediate_dump_writer.h" #include "util/ios/ios_intermediate_dump_writer.h"
#include "util/ios/ios_system_data_collector.h" #include "util/ios/ios_system_data_collector.h"
@ -159,17 +163,27 @@ class InProcessHandler {
//! minidumps and trigger an upload if possible. //! minidumps and trigger an upload if possible.
//! //!
//! \param[in] annotations Process annotations to set in each crash report. //! \param[in] annotations Process annotations to set in each crash report.
//! \param[in] user_stream_sources An optional vector containing the
//! extensibility data sources to call on crash. Each time a minidump is
//! created, the sources are called in turn. Any streams returned are
//! added to the minidump.
void ProcessIntermediateDumps( void ProcessIntermediateDumps(
const std::map<std::string, std::string>& annotations); const std::map<std::string, std::string>& annotations,
const UserStreamDataSources* user_stream_sources);
//! \brief Requests that the handler convert a specific intermediate dump into //! \brief Requests that the handler convert a specific intermediate dump into
//! a minidump and trigger an upload if possible. //! a minidump and trigger an upload if possible.
//! //!
//! \param[in] path Path to the specific intermediate dump. //! \param[in] path Path to the specific intermediate dump.
//! \param[in] annotations Process annotations to set in each crash report. //! \param[in] annotations Process annotations to set in each crash report.
//! \param[in] user_stream_sources An optional vector containing the
//! extensibility data sources to call on crash. Each time a minidump is
//! created, the sources are called in turn. Any streams returned are
//! added to the minidump.
void ProcessIntermediateDump( void ProcessIntermediateDump(
const base::FilePath& path, const base::FilePath& path,
const std::map<std::string, std::string>& annotations = {}); const std::map<std::string, std::string>& annotations = {},
const UserStreamDataSources* user_stream_sources = {});
//! \brief Requests that the handler begin in-process uploading of any //! \brief Requests that the handler begin in-process uploading of any
//! pending reports. //! pending reports.
@ -239,7 +253,12 @@ class InProcessHandler {
//! \brief Writes a minidump to the Crashpad database from the //! \brief Writes a minidump to the Crashpad database from the
//! \a process_snapshot, and triggers the upload_thread_ if started. //! \a process_snapshot, and triggers the upload_thread_ if started.
void SaveSnapshot(ProcessSnapshotIOSIntermediateDump& process_snapshot); //! \param[in] user_stream_sources An optional vector containing the
//! extensibility data sources to call on crash. Each time a minidump is
//! created, the sources are called in turn. Any streams returned are
//! added to the minidump.
void SaveSnapshot(ProcessSnapshotIOSIntermediateDump& process_snapshot,
const UserStreamDataSources* user_stream_sources = {});
//! \brief Process a maximum of 20 pending intermediate dumps. Dumps named //! \brief Process a maximum of 20 pending intermediate dumps. Dumps named
//! with our bundle id get first priority to prevent spamming. //! with our bundle id get first priority to prevent spamming.
@ -284,3 +303,5 @@ class InProcessHandler {
} // namespace internal } // namespace internal
} // namespace crashpad } // namespace crashpad
#endif // CRASHPAD_CLIENT_IOS_HANDLER_IN_PROCESS_IN_PROCESS_HANDLER_H_

View File

@ -110,35 +110,35 @@ TEST_F(InProcessHandlerTest, TestPendingFileLimit) {
// Only process other app files. // Only process other app files.
CreateFiles(0, 20); CreateFiles(0, 20);
handler().ProcessIntermediateDumps({}); handler().ProcessIntermediateDumps({}, {});
VerifyRemainingFileCount(0, 0); VerifyRemainingFileCount(0, 0);
ClearFiles(); ClearFiles();
// Only process our app files. // Only process our app files.
CreateFiles(20, 20); CreateFiles(20, 20);
handler().ProcessIntermediateDumps({}); handler().ProcessIntermediateDumps({}, {});
VerifyRemainingFileCount(0, 20); VerifyRemainingFileCount(0, 20);
ClearFiles(); ClearFiles();
// Process all of our files and 10 remaining. // Process all of our files and 10 remaining.
CreateFiles(10, 30); CreateFiles(10, 30);
handler().ProcessIntermediateDumps({}); handler().ProcessIntermediateDumps({}, {});
VerifyRemainingFileCount(0, 20); VerifyRemainingFileCount(0, 20);
ClearFiles(); ClearFiles();
// Process 20 our files, leaving 10 remaining, and all other files remaining. // Process 20 our files, leaving 10 remaining, and all other files remaining.
CreateFiles(30, 10); CreateFiles(30, 10);
handler().ProcessIntermediateDumps({}); handler().ProcessIntermediateDumps({}, {});
VerifyRemainingFileCount(10, 10); VerifyRemainingFileCount(10, 10);
ClearFiles(); ClearFiles();
CreateFiles(0, 0); CreateFiles(0, 0);
handler().ProcessIntermediateDumps({}); handler().ProcessIntermediateDumps({}, {});
VerifyRemainingFileCount(0, 0); VerifyRemainingFileCount(0, 0);
ClearFiles(); ClearFiles();
CreateFiles(10, 0); CreateFiles(10, 0);
handler().ProcessIntermediateDumps({}); handler().ProcessIntermediateDumps({}, {});
VerifyRemainingFileCount(0, 0); VerifyRemainingFileCount(0, 0);
ClearFiles(); ClearFiles();
} }

View File

@ -20,8 +20,6 @@ static_library("handler") {
"handler_main.h", "handler_main.h",
"prune_crash_reports_thread.cc", "prune_crash_reports_thread.cc",
"prune_crash_reports_thread.h", "prune_crash_reports_thread.h",
"user_stream_data_source.cc",
"user_stream_data_source.h",
] ]
if (crashpad_is_mac) { if (crashpad_is_mac) {
@ -98,6 +96,8 @@ static_library("common") {
"crash_report_upload_thread.h", "crash_report_upload_thread.h",
"minidump_to_upload_parameters.cc", "minidump_to_upload_parameters.cc",
"minidump_to_upload_parameters.h", "minidump_to_upload_parameters.h",
"user_stream_data_source.cc",
"user_stream_data_source.h",
] ]
if (crashpad_is_apple) { if (crashpad_is_apple) {
sources += [ sources += [
@ -112,6 +112,7 @@ static_library("common") {
] ]
deps = [ deps = [
"../client:common", "../client:common",
"../minidump",
"../snapshot", "../snapshot",
"../util", "../util",
"../util:net", "../util:net",