mirror of
https://github.com/chromium/crashpad.git
synced 2025-01-14 01:08:01 +08:00
ios: Add crashpad_uptime_ns crash key to iOS reports.
This CL introduces a new crash key 'crashpad_uptime_ns' that records the number of nanoseconds between when Crashpad was initialized and when a snapshot is generated. Crashpad minidumps record the MDRawMiscInfo process_create_time using a sysctl(KERN_PROC).kp_proc.p_starttime. This time is used to display the 'uptime' of a process. However, iOS 15 and later has a feature that 'prewarms' the app to reduce the amount of time the user waits before the app is usable. This mean crashes that may happen immediately on startup would appear to happen minutes or hours after process creation time. While initial implementations of prewarming would include some parts of main, since iOS16 prewarming is complete before main, and therefore before Crashpad is typically initialized. Bug: crashpad:472 Change-Id: Iff960e37ae40121bd5927d319a2767d1cafce846 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/5171091 Reviewed-by: Ben Hamilton <benhamilton@google.com> Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Justin Cohen <justincohen@chromium.org>
This commit is contained in:
parent
98d0d86e76
commit
30b2f4ba38
@ -468,9 +468,12 @@ InProcessHandler::ScopedReport::ScopedReport(
|
||||
num_frames_(num_frames),
|
||||
rootMap_(writer) {
|
||||
DCHECK(writer);
|
||||
// Grab the report creation time before writing the report.
|
||||
uint64_t report_time_nanos = ClockMonotonicNanoseconds();
|
||||
InProcessIntermediateDumpHandler::WriteHeader(writer);
|
||||
InProcessIntermediateDumpHandler::WriteProcessInfo(writer, annotations);
|
||||
InProcessIntermediateDumpHandler::WriteSystemInfo(writer, system_data);
|
||||
InProcessIntermediateDumpHandler::WriteSystemInfo(
|
||||
writer, system_data, report_time_nanos);
|
||||
}
|
||||
|
||||
InProcessHandler::ScopedReport::~ScopedReport() {
|
||||
|
@ -616,7 +616,8 @@ void InProcessIntermediateDumpHandler::WriteProcessInfo(
|
||||
// static
|
||||
void InProcessIntermediateDumpHandler::WriteSystemInfo(
|
||||
IOSIntermediateDumpWriter* writer,
|
||||
const IOSSystemDataCollector& system_data) {
|
||||
const IOSSystemDataCollector& system_data,
|
||||
uint64_t report_time_nanos) {
|
||||
IOSIntermediateDumpWriter::ScopedMap system_map(
|
||||
writer, IntermediateDumpKey::kSystemInfo);
|
||||
|
||||
@ -702,6 +703,11 @@ void InProcessIntermediateDumpHandler::WriteSystemInfo(
|
||||
} else {
|
||||
CRASHPAD_RAW_LOG("host_statistics");
|
||||
}
|
||||
|
||||
uint64_t crashpad_uptime_nanos =
|
||||
report_time_nanos - system_data.InitializationTime();
|
||||
WriteProperty(
|
||||
writer, IntermediateDumpKey::kCrashpadUptime, &crashpad_uptime_nanos);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -56,8 +56,12 @@ class InProcessIntermediateDumpHandler final {
|
||||
//! \brief Write SystemSnapshot data to the intermediate dump.
|
||||
//!
|
||||
//! \param[in] writer The dump writer
|
||||
//! \param[in] system_data An object containing various system data points.
|
||||
//! \param[in] report_time Report creation time in nanoseconds as returned by
|
||||
//! ClockMonotonicNanoseconds().
|
||||
static void WriteSystemInfo(IOSIntermediateDumpWriter* writer,
|
||||
const IOSSystemDataCollector& system_data);
|
||||
const IOSSystemDataCollector& system_data,
|
||||
uint64_t report_time_nanos);
|
||||
|
||||
//! \brief Write ThreadSnapshot data to the intermediate dump.
|
||||
//!
|
||||
|
@ -61,8 +61,8 @@ class InProcessIntermediateDumpHandlerTest : public testing::Test {
|
||||
InProcessIntermediateDumpHandler::WriteHeader(writer_.get());
|
||||
InProcessIntermediateDumpHandler::WriteProcessInfo(
|
||||
writer_.get(), {{"before_dump", "pre"}});
|
||||
InProcessIntermediateDumpHandler::WriteSystemInfo(writer_.get(),
|
||||
system_data_);
|
||||
InProcessIntermediateDumpHandler::WriteSystemInfo(
|
||||
writer_.get(), system_data_, ClockMonotonicNanoseconds());
|
||||
InProcessIntermediateDumpHandler::WriteThreadInfo(writer_.get(), 0, 0);
|
||||
InProcessIntermediateDumpHandler::WriteModuleInfo(writer_.get());
|
||||
}
|
||||
@ -161,9 +161,10 @@ TEST_F(InProcessIntermediateDumpHandlerTest, TestAnnotations) {
|
||||
path(), {{"after_dump", "post"}}));
|
||||
|
||||
auto process_map = process_snapshot.AnnotationsSimpleMap();
|
||||
EXPECT_EQ(process_map.size(), 2u);
|
||||
EXPECT_EQ(process_map.size(), 3u);
|
||||
EXPECT_EQ(process_map["before_dump"], "pre");
|
||||
EXPECT_EQ(process_map["after_dump"], "post");
|
||||
EXPECT_TRUE(process_map.find("crashpad_uptime_ns") != process_map.end());
|
||||
|
||||
std::map<std::string, std::string> all_annotations_simple_map;
|
||||
std::vector<AnnotationSnapshot> all_annotations;
|
||||
|
@ -122,6 +122,9 @@ bool ProcessSnapshotIOSIntermediateDump::InitializeWithFileInterface(
|
||||
}
|
||||
system_.Initialize(system_info);
|
||||
|
||||
annotations_simple_map_["crashpad_uptime_ns"] =
|
||||
std::to_string(system_.CrashpadUptime());
|
||||
|
||||
// Threads
|
||||
const IOSIntermediateDumpList* thread_list =
|
||||
GetListFromMap(root_map, Key::kThreads);
|
||||
|
@ -160,6 +160,10 @@ class ProcessSnapshotIOSIntermediateDumpTest : public testing::Test {
|
||||
EXPECT_TRUE(writer->AddProperty(Key::kWired, &count));
|
||||
EXPECT_TRUE(writer->AddProperty(Key::kFree, &count));
|
||||
}
|
||||
|
||||
uint64_t crashpad_report_time_nanos = 1234567890;
|
||||
EXPECT_TRUE(
|
||||
writer->AddProperty(Key::kCrashpadUptime, &crashpad_report_time_nanos));
|
||||
}
|
||||
|
||||
void WriteAnnotations(IOSIntermediateDumpWriter* writer,
|
||||
@ -491,6 +495,9 @@ class ProcessSnapshotIOSIntermediateDumpTest : public testing::Test {
|
||||
ExpectModules(
|
||||
snapshot.Modules(), expect_module_path, expect_long_annotations);
|
||||
ExpectMachException(*snapshot.Exception());
|
||||
|
||||
auto map = snapshot.AnnotationsSimpleMap();
|
||||
EXPECT_EQ(map["crashpad_uptime_ns"], "1234567890");
|
||||
}
|
||||
|
||||
void CloseWriter() { EXPECT_TRUE(writer_->Close()); }
|
||||
|
@ -119,6 +119,8 @@ void SystemSnapshotIOSIntermediateDump::Initialize(
|
||||
}
|
||||
}
|
||||
|
||||
GetDataValueFromMap(system_data, Key::kCrashpadUptime, &crashpad_uptime_ns_);
|
||||
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
}
|
||||
|
||||
@ -249,5 +251,10 @@ uint64_t SystemSnapshotIOSIntermediateDump::AddressMask() const {
|
||||
return address_mask_;
|
||||
}
|
||||
|
||||
uint64_t SystemSnapshotIOSIntermediateDump::CrashpadUptime() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return crashpad_uptime_ns_;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
||||
|
@ -75,6 +75,10 @@ class SystemSnapshotIOSIntermediateDump final : public SystemSnapshot {
|
||||
std::string* daylight_name) const override;
|
||||
uint64_t AddressMask() const override;
|
||||
|
||||
//! \brief Returns the number of nanoseconds between Crashpad initialization
|
||||
//! and snapshot generation.
|
||||
uint64_t CrashpadUptime() const;
|
||||
|
||||
private:
|
||||
std::string os_version_build_;
|
||||
std::string machine_description_;
|
||||
@ -93,6 +97,7 @@ class SystemSnapshotIOSIntermediateDump final : public SystemSnapshot {
|
||||
std::string standard_name_;
|
||||
std::string daylight_name_;
|
||||
uint64_t address_mask_;
|
||||
uint64_t crashpad_uptime_ns_;
|
||||
InitializationStateDcheck initialized_;
|
||||
};
|
||||
|
||||
|
@ -86,6 +86,7 @@ namespace internal {
|
||||
TD(kInactive, 5018) \
|
||||
TD(kWired, 5019) \
|
||||
TD(kAddressMask, 5020) \
|
||||
TD(kCrashpadUptime, 5021) \
|
||||
TD(kThreads, 6000) \
|
||||
TD(kDebugState, 6001) \
|
||||
TD(kFloatState, 6002) \
|
||||
|
@ -44,6 +44,7 @@ class IOSSystemDataCollector {
|
||||
const std::string& DaylightName() const { return daylight_name_; }
|
||||
bool IsApplicationActive() const { return active_; }
|
||||
uint64_t AddressMask() const { return address_mask_; }
|
||||
uint64_t InitializationTime() const { return initialization_time_ns_; }
|
||||
|
||||
// Currently unused by minidump.
|
||||
int Orientation() const { return orientation_; }
|
||||
@ -82,6 +83,12 @@ class IOSSystemDataCollector {
|
||||
std::string daylight_name_;
|
||||
ActiveApplicationCallback active_application_callback_;
|
||||
uint64_t address_mask_;
|
||||
|
||||
// Time in nanoseconds as returned by ClockMonotonicNanoseconds() to store the
|
||||
// crashpad start time. This clock increments monotonically but pauses while
|
||||
// the system is asleep. It should not be compared to other system time
|
||||
// sources.
|
||||
uint64_t initialization_time_ns_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "build/build_config.h"
|
||||
#include "util/misc/clock.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -86,7 +87,8 @@ IOSSystemDataCollector::IOSSystemDataCollector()
|
||||
standard_offset_seconds_(0),
|
||||
daylight_offset_seconds_(0),
|
||||
standard_name_(),
|
||||
daylight_name_() {
|
||||
daylight_name_(),
|
||||
initialization_time_ns_(ClockMonotonicNanoseconds()) {
|
||||
NSOperatingSystemVersion version =
|
||||
[[NSProcessInfo processInfo] operatingSystemVersion];
|
||||
major_version_ = base::saturated_cast<int>(version.majorVersion);
|
||||
|
Loading…
x
Reference in New Issue
Block a user