NEW REPORT! Defining and measuring mobile SLOs: Best practices for modern DevOps, SRE, and mobile teams

Download report
Crash Reporting

Understanding SIGKILLs in iOS

As an iOS developer, understanding SIGKILLs is vital. The right understanding helps you problem solving faster, produce highly performant apps, and save valuable development time that can be refocused on innovation.

As an iOS developer, it’s important to understand SIGKILL signals because this knowledge helps in debugging and troubleshooting issues with an app. If an app is unexpectedly terminated and you suspect that a SIGKILL signal was sent to it, you’ll need to investigate factors like the launch speed and memory usage patterns to identify opportunities for optimization.

In this blog, we’ll discuss the following:

  • Why solving a SIGKILL is difficult
  • Common types of SIGKILLs
  • How to prevent SIGKILLs from occurring

Why solving a SIGKILL is difficult

A SIGKILL is a signal that is sent in the event that your code violates one of Apple’s pre-defined rules. A crash occurs when code runs in an unexpected manner that the program cannot recover from. Both issues result in the app’s process being terminated.

It’s also important to note that a SIGKILL is one type of signal, while there are many different kinds across iOS. You can read more about the rest here.

Although how SIGKILLs occur may seem straightforward, the process quickly becomes obscure when you lack the expertise or information necessary to combat this problem. Many intermediate developers lack the extensive experience necessary to solve SIGKILLs with both speed and precision. In addition to this, as you’ve likely heard many people say before, “Apple is security through obscurity.” The lack of information that Apple provides surrounding this topic can lead to wasted developer time and frustration when trying to solve difficult crashes.

Common types of SIGKILLs

To properly interpret a SIGKILL, you’ll need to thoroughly understand SIGKILLs and understand the reasons that contribute to them.

You can reference Apple’s documentation for more information about SIGKILLs. Below, we’ll dive into some of the most common types of SIGKILLs along with vital information to help solve these issues.

Launch

A launch SIGKILL is a type of SIGKILL that is sent by the iOS launch daemon. This launch daemon is responsible for starting and managing system services and background processes.

When your app is launched, the launch daemon initiates a sequence of events to start the app’s process and prepare it for execution. If the launch daemon detects that the app’s process is taking too long to start or is not responding within an appropriate amount of time, it sends a SIGKILL signal to terminate the process.

The launch SIGKILL signal is typically sent after a configurable timeout period has elapsed. The timeout is based on the iOS version, the entitlements of the app, and Apple’s current launch timeout policy.

Apps follow a specific life cycle during a launch. First, ApplicationDidFinishLaunching is called, and then many other things may happen depending on the specifics of the app. There is a specific callback, ViewDidAppear, which means the app view is now visible on the screen and is interactable. The code that happens in between these two callbacks (including what’s in ApplicationDidFinishLaunching but not including what’s in ViewDidAppear) is what affects your launch times.

Memory

A memory SIGKILL is a type of SIGKILL that is sent when an app exceeds its allocated memory limit or the device is running out of memory while the app is not in the foreground. This can happen when an app is using too much memory or when it is holding on to memory that is no longer needed. The memory SIGKILL is sent to terminate the app’s process and prevent it from consuming excessive resources or causing other issues on the device.

We’ll walk through two examples of this below.

Memory leak

A memory leak occurs when an object is no longer referenced anywhere in your code. In other words, you create an object for use, finish using that object, and then the object never gets deallocated. This can only happen in Swift and Objective C via a “retain cycle.”

Retain cycles are the result of two objects strongly referencing each other. A common example would be holding a reference to a dispatch block while that dispatch block contains a strong reference to self.

Here is a retain cycle pseudo code example:

class RetainCycleObject: NSObject{
var SomeBlock: (() -> Void)!
var titleLabel : UILabel

init(viewModel: BlueViewModel) {
titleLabel = UILabel()
SomeBlock = {
self.titleLabel.text = viewModel.titleText
}
}
}

Memory abandonment

Memory abandonment occurs when the app is holding on to an object that the app no longer requires.

This type of memory bug can almost always be found using the Xcode analyze tool. This is a tool that statically reads the code and shows the possible issues with it.

Image of the Xcode analyze tool in action.

To use this tool, all you need to do is use the menu option, navigate to “Product,” and then to “Analyze” while in Xcode. This feature, which works for Objective C, compiles your code, runs the tool, and then highlights areas it deems problematic. Using this tool is advantageous because it finds problems before they pose an issue to your app in production.

How to prevent SIGKILLs from occurring

After troubleshooting a SIGKILL, the next step is to prevent future SIGKILLs from occurring. Here are a few methods you can use to do so.

Implement proper memory management techniques

In practice, implementing proper memory management techniques involves deallocating objects, using weak references where necessary, and avoiding the retain cycles mentioned above.

Minimize background processing and network usage

Background processing and excessive network usage both drain system resources and lead to SIGKILLs. iOS developers should only perform necessary tasks in the background and use network resources efficiently.

Optimize system resource usage

Developers should optimize the usage of system resources like CPU, memory, and disk space. This can be achieved by reducing image sizes, compressing data, and optimizing database queries.

Final thoughts

Understanding SIGKILLs is crucial for iOS developers. This is because the right knowledge about SIGKILLs empowers developers to be more efficient in their problem-solving process, take proactive steps to prevent SIGKILLs from occurring, and diagnose and fix issues quickly. This produces more stable and performant apps, improves the user experience, and makes the mobile app development process faster, easier, and more efficient.

Want to solve your SIGKILL issues with ease? Explore Embrace today.

Embrace Deliver incredible mobile experiences with Embrace.

Get started today with 1 million free user sessions.

Get started free

Build better mobile apps with Embrace

Find out how Embrace helps engineers identify, prioritize, and resolve app issues with ease.