Own Your Crash Logs with PLCrashReporter: Part 3
iOSIn the third post of our PLCrashReporter series, we will walk through how to get PLCrashReporter up and running on your machine. And make...
Welcome to the PLCrashReporter blog post series. For those unfamiliar with this crash reporting library, it is defined as follows:
PLCrashReporter is a reliable open source library that provides an in-process live crash reporting framework for use on iOS, macOS, and tvOS. The library detects crashes and generates reports to help your investigation and troubleshooting with the information of application, system, process, thread, etc. as well as stack traces.
In the upcoming posts we will first dive deep into crashes by covering:
Then, we will provide you with a step-by-step tutorial on how to get PLCrashReporter up and running.
You’re curious about crashes – What even is a crash? Obvious questions can be difficult to answer. If there’s a chance you might get asked this in an interview, you’ll be better prepared to answer it after reading.
You want to know how crash logs are created – You’re equally horrified and mesmerized by whatever dark art must be summoned to intercept a crash and finagle it into some useful output.
You’re interested in PLCrashReporter – You’ve heard of PLCrashReporter before but have never peeked under the hood or used it in a project. Now’s your chance. [1]
You’re looking for an alternative to third-party crash reporting services – There are a number of reasons why you wouldn’t want to use a paid crash reporting service. Your institution might not permit closed-source libraries, which most (perhaps all?) third-party crash reporters require. Third-party services cost money, which is a deal-breaker for some small projects. Some have dubious privacy policies that might permit them to gather more than just crash logs. Or a Facebook bug might bring down their infrastructure, leaving your app in the lurch.
You need an alternative to TestFlight and App Store crash reporting for internal distributions – TestFlight gathers crash logs for you, which appear in the Xcode Organizer, but these are, naturally, only available for TestFlight builds. If you’re using Enterprise or Ad Hoc distribution, you need another way to gather development-build crash logs.
If none of these describe you, well, you should keep reading anyway, because what have you got to lose?
It seems obvious, but let’s ask the question: what is a crash? The video for WWDC 2008 session 414 says it well:
A crash is a sudden termination of your app when it attempts to do something that is not allowed.
There are a number of types of crashes. Let’s take a look at them.
First, there are assertions and preconditions. These occur when code, either in your own source or in libraries that your source is using, deliberately stops the process. For example:
!
postfix operator will terminate the process if code attempts to unwrap a .none
value.Next, there are terminations by the operating system, i.e. something that results in your process receiving the SIGKILL
signal. We’ll delve into signals more in the next post. Some examples of these terminations:
Last, but certainly not least, there are memory errors. Our old pal EXC_BAD_ACCESS
. Memory errors are some of the most troublesome issues to debug, particularly when multi-threading or manual reference-counting is involved. Some examples:
objc_release
message to an object that already has a zero reference count is not allowed.Swift.Array
and NSArray
, which proactively look for out-of-bounds accesses.Stack overflow refers specifically to the case when the execution stack grows beyond the memory that is reserved for it. For example, if you call a function which recursively calls itself without termination, you will cause a stack overflow as each function call creates a new stack frame and the stack will eventually consume more memory than is reserved for it. (Nick Meyer, “What is the difference between a stack overflow and buffer overflow?”)
If an app crashes in the woods, but there was no log left behind, would anyone be able to fix it? A detailed, accurate crash log is necessary to correctly diagnose a crash. So what transpires between the moment a process is notified of an impending crash and when the crash log is written to disk? There are, on Apple platforms, two mechanisms that produce crash logs:
.crash
log. Those logs are stashed in an OS-specific location for later use. This all happens outside of your app’s process. If the crashed app was distributed via Test Flight or the App Store, the crash log will also be uploaded to App Store Connect servers and can be viewed in the Xcode Organizer.The differences between capturing crashes in-process and capturing them out-of-process is more than superficial. There are profound risks and challenges to overcome to safely and reliably capture crashes in-process. Like all third-party crash reporting tools, PLCrashReporter is obligated to run in-process. These challenges will be a recurring theme across future posts in this series.
That’s it for the first post in the series! Next, we will discuss crash log creation, POSIX signals, Mach exceptions, and async-signal safety.
[1] From Plausible Labs website: “PLCrashReporter was the first crash logging solution available for iOS. Today, PLCrashReporter is used by most 3rd-party crash logging services for iOS and macOS, and can be found reporting crashes in the Netflix, Amazon Prime Video, Dropbox, Yahoo Mail, Kindle, and Chase Mobile iOS apps, as well as tens of thousands of other applications. With Microsoft’s purchase of HockeyApp in 2014, PLCrashReporter sits at the core of Microsoft’s crash logging solutions for Apple’s platforms. And in October 2019, Plausible and Microsoft reached an agreement to transfer stewardship of PLCrashReporter to the App Center team at Microsoft, where it will continue to be developed as an open-source project.
In the third post of our PLCrashReporter series, we will walk through how to get PLCrashReporter up and running on your machine. And make...
In part two of our PLCrashReporter series, we will examine how crashes are created and learn more about specific crash types.
GraphQL can revolutionize your product by improving performance, reducing friction between development teams, and even helping with documentation. But it's important to understand the...