ios: Add iOS crashpad overview documentation.
Adds an overview of the limitations of crashpad on the iOS platform,
including explanations of the in-process client and handler, and the
intermediate dump format used.
Bug: crashpad: 31
Change-Id: Ia70dc90067d882a7bdd9ffa524b187b6cce8fecf
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2706018
Commit-Queue: Justin Cohen <justincohen@chromium.org>
Reviewed-by: Mark Mentovai <mark@chromium.org>
GitOrigin-RevId: 2dbd019bc2303a0463a396b5c47b4eb16a1a1e27
diff --git a/client/crashpad_client.h b/client/crashpad_client.h
index cbe0551..ec6c5e5 100644
--- a/client/crashpad_client.h
+++ b/client/crashpad_client.h
@@ -485,18 +485,37 @@
//! \brief Requests that the handler begin in-process uploading of any
//! pending reports.
//!
+ //! Once called the handler will start looking for pending reports to upload
+ //! on another thread. This method does not block.
+ //!
//! A handler must have already been installed before calling this method.
- void EnableUploading();
+ void StartProcesingPendingReports();
- // TODO(justincohen): This method is purely for bringing up iOS interfaces.
- //! \brief Requests that the handler capture a dump even though there hasn't
- //! been a crash.
+ //! \brief Requests that the handler capture an intermediate dump even though
+ //! there hasn't been a crash. The intermediate dump will be converted
+ //! to a mindump immediately. If StartProcesingPendingReports() has been
+ //! called, this will also trigger an upload.
+ //!
+ //! For internal use only. Clients should use CRASHPAD_SIMULATE_CRASH().
//!
//! A handler must have already been installed before calling this method.
//!
//! \param[in] context A NativeCPUContext, generally captured by
//! CaptureContext() or similar.
static void DumpWithoutCrash(NativeCPUContext* context);
+
+ //! \brief Requests that the handler capture an intermediate dump even though
+ //! there hasn't been a crash. The intermediate dump will not be converted
+ //! to a mindump until ProcessIntermediateDumps() is called.
+ //!
+ //! For internal use only. Clients should use
+ //! CRASHPAD_SIMULATE_CRASH_AND_DEFER_PROCESSING().
+ //!
+ //! A handler must have already been installed before calling this method.
+ //!
+ //! \param[in] context A NativeCPUContext, generally captured by
+ //! CaptureContext() or similar.
+ static void DumpWithoutCrashAndDeferProcessing(NativeCPUContext* context);
#endif
#if defined(OS_APPLE) || DOXYGEN
diff --git a/client/crashpad_client_ios.cc b/client/crashpad_client_ios.cc
index 588834c..6cbbb41 100644
--- a/client/crashpad_client_ios.cc
+++ b/client/crashpad_client_ios.cc
@@ -234,7 +234,7 @@
}
// static
-void CrashpadClient::EnableUploading() {
+void CrashpadClient::StartProcesingPendingReports() {
// TODO(justincohen): Start the CrashReportUploadThread.
}
@@ -243,7 +243,17 @@
CrashHandler* crash_handler = CrashHandler::Get();
DCHECK(crash_handler);
crash_handler->DumpWithoutCrash(context);
+ // TODO(justincohen): Change this to only process the dump from above, not all
+ // intermediate dump files.
crash_handler->ProcessIntermediateDumps();
}
+// static
+void CrashpadClient::DumpWithoutCrashAndDeferProcessing(
+ NativeCPUContext* context) {
+ CrashHandler* crash_handler = CrashHandler::Get();
+ DCHECK(crash_handler);
+ crash_handler->DumpWithoutCrash(context);
+}
+
} // namespace crashpad
diff --git a/client/crashpad_client_ios_test.mm b/client/crashpad_client_ios_test.mm
index 5bc3946..30fabae 100644
--- a/client/crashpad_client_ios_test.mm
+++ b/client/crashpad_client_ios_test.mm
@@ -18,6 +18,7 @@
#include <vector>
+#include "client/simulate_crash.h"
#include "gtest/gtest.h"
#include "test/scoped_temp_dir.h"
#include "testing/platform_test.h"
@@ -33,9 +34,7 @@
ScopedTempDir database_dir;
client.StartCrashpadInProcessHandler(
base::FilePath(database_dir.path()), "", {});
- NativeCPUContext context;
- CaptureContext(&context);
- client.DumpWithoutCrash(&context);
+ CRASHPAD_SIMULATE_CRASH();
}
// This test is covered by a similar XCUITest, but for development purposes it's
diff --git a/client/simulate_crash_ios.h b/client/simulate_crash_ios.h
index 3cd1a69..87a9457 100644
--- a/client/simulate_crash_ios.h
+++ b/client/simulate_crash_ios.h
@@ -20,7 +20,11 @@
//! \file
-//! \brief Captures the CPU context and captures a dump without an exception.
+//! \brief Captures the CPU context and creates a minidump dump without an
+//! exception. The minidump will immediately become eligible for further
+//! processing, including upload.
+//!
+//! \sa CRASHPAD_SIMULATE_CRASH_AND_DEFER_PROCESSING
#define CRASHPAD_SIMULATE_CRASH() \
do { \
crashpad::NativeCPUContext cpu_context; \
@@ -28,4 +32,19 @@
crashpad::CrashpadClient::DumpWithoutCrash(&cpu_context); \
} while (false)
+//! \brief Captures the CPU context and captures an intermediate dump without an
+//! exception. Does not convert the intermediate dump into a minidump.
+//!
+//! Deferring processing is useful when the application may be in an unstable
+//! state, such as during a hang.
+//!
+//! \sa CRASHPAD_SIMULATE_CRASH
+#define CRASHPAD_SIMULATE_CRASH_AND_DEFER_PROCESSING() \
+ do { \
+ crashpad::NativeCPUContext cpu_context; \
+ crashpad::CaptureContext(&cpu_context); \
+ crashpad::CrashpadClient::DumpWithoutCrashAndDeferProcessing( \
+ &cpu_context); \
+ } while (false)
+
#endif // CRASHPAD_CLIENT_SIMULATE_CRASH_IOS_H_
diff --git a/doc/ios_overview_design.md b/doc/ios_overview_design.md
new file mode 100644
index 0000000..be23d09
--- /dev/null
+++ b/doc/ios_overview_design.md
@@ -0,0 +1,104 @@
+<!--
+Copyright 2021 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.
+-->
+
+# iOS Crashpad Overview Design
+
+[TOC]
+
+## iOS Limitations
+
+Crashpad on other platforms captures exceptions out-of-process. The iOS sandbox,
+however, restricts applications from delegating work to separate processes.
+This limitation means Crashpad on iOS must combine the work of the handler and
+the client into the same process as the main application.
+
+## The Crashpad In-Process Handler
+
+In-process handling comes with a number of limitations and difficulties. It is
+not possible to catch the specific Mach exception `EXC_CRASH`, so certain groups
+of crashes cannot be captured. This includes some major ones, like out-of-memory
+crashes. This also introduces difficulties in capturing all the relevant crash
+data and writing the minidump, as the process itself is in an unsafe state.
+
+While handling an exception, the handler may not, for example:
+
+ - Allocate memory.
+ - Use libc, or most any library call.
+
+While handling an exception, the handler may only:
+
+ - Use audited syscalls.
+ - access memory via `vm_read`.
+
+In conjunction with Crashpad’s existing minidump writer and structural
+limitations of the minidump format, it is not possible to write a minidump
+immediately from the crash handler. Instead, an intermediate dump is written
+when a handler would normally write a minidump (such as during an exception or a
+forced dump without crashing). The intermediate dump file will be converted to
+a minidump on the next run (or when the application decides it's safe to do so).
+
+During Crashpad initialization, the handler gathers basic system information
+and opens a pending intermediate dump adjacent to the Crashpad database.
+
+## The Crashpad IntermediateDump Format
+
+Due to the limitations of in-process handling, an intermediate dump file is
+written during exceptions. The data is streamed to a file, which will be used to
+generate a final minidump when appropriate.
+
+The file format is similar to binary JSON, supporting keyed properties, maps and
+arrays.
+
+ - `Property` [key:int, length:int, value:intarray]
+ - `StartMap` [key:int], followed by repeating Properties until `EndMap`
+ - `StartArray` [key:int], followed by repeating Maps until `EndArray`
+ - `EndMap`, `EndArray`, `EndDocument`
+
+Similar to JSON, maps can contain other maps, arrays and properties.
+
+## The Crashpad In-Process Client
+
+Other Crashpad platforms handle exceptions and upload minidumps out-of-process.
+On iOS, everything must happen in-process. Once started, the client will
+automatically handle exceptions and capture the crashed process state in an
+intermediate dump file. Converting that intermediate dump file into a minidump
+is likely not safe to do from within a crashed process, and uploading a minidump
+is definitely unsafe to do at crash time. Applications are expected to process
+intermediate dumps into pending minidumps and begin processing pending
+minidumps, possibly for upload, at suitable times following the next application
+restart.
+
+
+### `ProcessIntermediateDumps`
+For performance and stability reasons applications may choose the correct time
+to convert intermediate dumps, as well as append metadata to the pending
+intermediate dumps. This is expected to happen during application startup, when
+suitable. After converting, a minidump will be written to the Crashpad database,
+similar to how other platforms write a minidump on exception handling. If
+uploading is enabled, this minidump will also be immediately uploaded. New
+intermediate dumps generated by exceptions or by
+`CRASHPAD_SIMULATE_CRASH_AND_DEFER_PROCESSING` will will not be processed until
+the next call to `ProcessIntermediateDumps`. Conversely,
+`CRASHPAD_SIMULATE_CRASH` can be called when the client has no performance or
+stability concerns. In this case, intermediate dumps are automatically
+converted to minidumps and immediately eligable for uploading.
+
+### `StartProcesingPendingReports`
+For similar reasons, applications may choose the correct time to begin uploading
+pending reports, such as when ideal network conditions exist. By default,
+clients start with uploading disabled. Applications should call this API when
+it is determined that it is appropriate to do so (such as on a few seconds after
+startup, or when network connectivity is appropriate).
diff --git a/doc/overview_design.md b/doc/overview_design.md
index 9d0f0ed..01dba17 100644
--- a/doc/overview_design.md
+++ b/doc/overview_design.md
@@ -93,7 +93,8 @@
responsible for snapshotting the crashing client process’ state on a crash,
saving it to a crash dump, and transmitting the crash dump to an upstream
server. Clients register with the handler to allow it to capture and upload
-their crashes.
+their crashes. On iOS, there is no separate process for the handler.
+[This is a limitation of iOS.](ios_overview_design.md#ios-limitations)
### The Crashpad handler
@@ -213,6 +214,12 @@
existing crash handler, which can be necessary when an older client spawns an
updated version.
+#### iOS
+
+iOS registers both a signal handler for `SIGABRT` and a Mach exception handler
+with a subset of available exceptions. [This is a limitation of
+iOS.](ios_overview_design.md#ios-limitations)
+
#### Windows
There are two modes of registration on Windows. In both cases the handler is
@@ -272,6 +279,14 @@
entirely from the Crashpad handler without the need to run any code in the crash
process at the time of the exception.
+#### iOS
+
+On iOS, the operating system will notify the handler of crashes via the Mach
+exception port or the signal handler. As exceptions are handled in-process, an
+intermediate dump file is generated rather than a minidump. See more
+information about the [iOS in-process
+handler.](ios_overview_design.md#ios-in-process-handler)
+
#### Windows
On Windows, the OS dispatches exceptions in the context of the crashing thread.
@@ -415,6 +430,14 @@
The macOS implementation simply stores database properties on the minidump files
in filesystem extended attributes.
+#### iOS
+
+The iOS implementation also stores database properties of minidump files in
+filesystem extended attributes. Separate from the database, iOS also stores its
+intermediate dump files adjacent to the database. See more information about
+[iOS intermediate
+dumps.](ios_overview_design.md#the-crashpad-intermediatedump-format)
+
#### Windows
The Windows implementation stores database properties in a binary file named