How to get error reports of a freezing iOS app? - ios

Recently I had an issue in my iOS app that caused the app to freeze. The UI was unresponsive and the user had to kill and restart the app to make it work again.
In Google's Play Console I see such issues as ANRs ('Application not responding' errors).
But in Xcode I don't get any reports unfortunately. Crashlytics also didn't show any reports.
Is it possible to somehow get some kind of report with a stacktrace similar to the ANRs in Google's Play Console?
Please note:
I know what caused the app to freeze in this specific issue and also how to debug and fix it. What I
want is an error report in case the issue wasn't found during QA but it is
occurring in a user session.
The freezing version was not published to App Store, only to
TestFlight.

The reason for unresponsive UIs could be due to a number of reasons:
One reason could be because of high load (running out of RAM, Swap Space). For detecting these scenarios (without crashing behavior) you need Application Performance Monitoring, for example with Firebase. The advantage with Firebase is you don't have to prompt for consent, so you get more data to detect hangs. The Xcode Organizer can provide Hang Rate metrics though if you have enough users who have consented to share their data (new in Xcode 11).
Another reason could be due to logical errors in code. For example, a user triggers an unexpected app flow that was missed during manual testing. In these instances, it can be harder to narrow down but could be trackable with manual user testing beforehand e.g TestFlight. You can use In-App Feedback tools (users send you emails) to gather context about the issue or Instabug for screenshots and advanced feedback.
The other reason could be because of deadlocks. If you use DispatchGroup for instance or DispatchSemaphores to queue network requests and the requests time out then that could also lead to suspended UI frames. I would look carefully at where you leave the dispatch group as well - all possible branches should have a dispatch_group_leave statement to avoid hanging on dispatch_group_wait.
You can use the Thread State Trace Instrument to see whether system calls are blocking your main thread to debug this issue. The classic iOS dev advice is to only perform UI updates on the main thread and move all other logic to a background thread. This may not solve the root cause but does prevent hangs. The same logic applies for Core Data fetches, inserts, deletes, and updates. Move Core Data operations to background threads in network request callbacks as well.
If you get crash reports, it's simple to diagnose an OOM error in a Crashlytics crash report for example (comes up in Insights). Heap corruption can also be inferred from crash reports, and while the metadata may not be the same for the same behavior, it could point you to a screen or action when you try and reproduce the bug.
Watchdog Unresponsive App crashes can be intercepted to come up in crash reports if the user doesn't kill the app beforehand, but you mentioned the user killed the app so this may not be available.
There is no direct equivalent ANR error reporting for iOS apps, given that Hang Rates are only aggregated if enough sessions have been detected. You could do screen recording of app sessions (ServiceNow), but I don't advise it because it has privacy implications.

Crashlytics is unable to send abnormal terminations fired by the watchdog. I've researched this for Jetsam terminations. You will see them in the console logs. see this link for the watchdog crash iOS generates: Watchdog Unresponsive App. If there's a way to monitor the main thread for queued operations executing for too long, you could fire a fatal error ie fire a fatal before the watchdog terminates the app.

Do some research on MetricKit. It's new to iOS 13. There's a class called MXHangDiagnostic. You can use it in your app to monitor for hangs and report on them as you see fit.

Related

iOS app getting killed in background - how to debug?

My iOS app gets terminated when put in background. I get the following logs in the device console:
Background Task 160 (""), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this.
followed by
Background task still not ended after expiration handlers were called: . This app will likely be terminated by the system. Call UIApplication.endBackgroundTask(_:) to avoid this.
and the app terminates and restarts on resuming from background
The new metric kit background exit data (iOS 14) is also reporting that BackgroundTaskAssertionTimeoutExits are killing my app
On breaking on UIApplicationEndBackgroundTaskError, I get the following backtrace:
I have not implemented any background tasks myself but there are some third party libraries integrated in the app that do.
What is the right way to debug this?
If you did not start any background task, and you do not perform anything most likely some of your 3rd party frameworks are causing the crash.
Update to latest version of all your dependencies, to see if the issue was fixed.
If your issue is easily reproducible, try to disable them 1 by 1 to see which is causing the crash.
After that go on the library support page and see if there are any bugs for your issue and if not open a bug.
Start with the usual suspects, Analytics, Loggers and go on.
Have a look also at this thread: App is crashing on only iOS 13 in the background mode

iOS 12 terminates apps in the background for no reason

Starting from iOS 12 the CLLocationManager doesn't run endless anymore in the background. The app get's terminated without a crashlog at random times. This was working fine before iOS 12.
To demonstrate this problem I've created an sample app here
The demo app just launches an CLLocationManager and keep this running in the background. While running on the background we keep track of it by logging it. The problem is that the app get terminated by iOS. The demo app is created to demonstrate this problem.
Steps to reproduce
Run the app on the device
Grand access to locationmanager
Put the app to the background
Wait for 1-48hours
Result:
The app is terminated
App is terminated without any reason after random time.
Expected result:
The app is still running.
How it should work
This is confirmed by an Apple engineer:
Once the CLLocationManager updates are started in the foreground and you did all the work to have it running in the background, the location updates should run endless in the background until:
app is force quit
device is rebooted
app stops location updates
app releases the CLLocationManager object
app crashes
iOS terminates the app due to memory shortage,
the locationManager object is released, overreleased, or overwritten. You should make sure that your view controller is not being instantiated, which then resets the locationController class. If that happens when the app is in the background, you will restart updates, which will cause the app to be eventually suspended. You should make sure the locationController is a singleton.
app is crashing. Check to see if there are crash logs on the device you are testing
iOS is terminating the app due to memory shortage. In this case, you will find JetsamEvent logs on the device that shows your app being terminated. You can check the timestamps and locate the one that is around the time your app stopped working.
Updated answer:
Apple fixed this bug in iOS 12.2 beta 2 (16E5191d)
Original analyse and bug detection:
Together with Apple Developer Technical Support we have analyzed this issue with Sysdiagnose files. Following these guidelines you can install profiles to have more logging on your device. I don't know exactly how these logs work and where to find this issue, but Apple did this for me and came with this first analyse:
On the suspension event you observed on 2018/10/22 01:01:12:587, this
is what I see (about a minute after your last activity logging)
[CllocationManag:2725] Terminating with description:
{
owner = ;
target = rw.sp.flitsmeister.frameworks.CllocationManagerBackgroundTest; }
This is basically saing that your app was terminated, because the
system needed drive space, and killed a bunch of apps so it can delete
their /tmp and /Library/Caches directories. I have seen this process
to be a little more aggressive in iOS 12, but seeing you are on a
256GB device, and have ~179 GB free after the cleanup, I am finding it
hard to believe this was justified.
After sending some more sysdiagnose and reproduction cases Apple did his best to analyse and ended with the following conclusion:
Unfortunately I don’t bring good news.
It turned out that, currently in iOS 12 there is a new mechanism that
will terminate long running background apps periodically as the system
needs to free resources. At this time, this process is a bit too
aggressive, and I am working with the relevant teams to get this to
behave better.
So, at this point, I would like you to file a bug report. Explain the
symptoms. And make sure you upload the sysdiagnose files along with
the bug report. (I already sent yours in, but it doesn’t hurt to have
the new ones as well). And let me know the bug number please.
So this means that currently in iOS 12 you app won't run endless on the background. I've filled in a bug report, the number is 45581276 and will try to keep this thread updated.
I tried clearing out the /tmp and /Library/Caches directories when the app goes in the background without any change in behavior. I also tried the same periodically when the app processing background locations without any change as well.

Crashlytics for iOS does logs crash only when app is opened after the crash

In an iOS Mobile App why does crashlytics log crash and send email, when the iOS app is opened after the crash. This behavior is not consistent when crashlytics is integrated with android app.
Typically after a crash, user will stop using the app and not open it again. As a consequence we end up missing several crashes which happen in iOS.
Mike from Fabric here. The behavior is different on each platform since each platform has different behaviors for exception handling and networking.
On iOS, it's unsafe to send much, if any, data after an exception happens that leads to a crash. The app is a horrible state and the device is also resolving an unexpected situation. If, we or other services, tried to send additional data then, you could run the risk of causing an issue on the entire device which it would require the device to restart. Asking a user to restart their device is a much worse behavior then having them need to relaunch the app.
You are correct that some users may never relaunch the app and those crashes are lost, but in general, we've found most users relaunch the app post-crash.
As #Dev_Tandel said, on Android, other background networking services can be used to try and send the crash report then. We will try to do that, but don't guarantee that a report will be sent until the app is relaunched.

When I close the application I got Message from debugger: Terminated due to signal 15

How can I solve this problem, I don't know that did it affect to my problem in this link My previous problem about Core data ?
This message will occur when I cmd+Q of the application.
Message from debugger: Terminated due to signal 15
and if who know the solution of my previous problem please tell me.
Message from debugger: Terminated due to signal 15 occurs whenever the user manually terminates the application (whether simulated in iOS simulator or on a provisioned iOS device) through CMD-Q (Quit) or STOP, which is toggled after you click on RUN.
In OS terms, signal 15 is a Linux enumeration for the signal, SIGTERM, which means signal terminate.
Message from debugger: Terminated due to signal 15 usually means that you quit the simulator while running the program.
I have same issue when i take screen short from simulator then terminated. This is xcode bug.
Just update your xcode version.
This only means that the system sent your application the kill signal. The system may do that for any number of reasons. It does not necessarily mean the application was killed due to memory pressure. In fact, this is very unlikely in the case that you describe. Most of the reasons the system might send a kill signal won't happen when the app is being debugged.
When the system kills an application it will track the reason and log it. If you are using a third party crash reporting service this will not capture the reason, and in fact can prevent a lot of critical information from being logged by the system.
Look for logs on the device. Watch the console log on the device when the issues reproduces - usually you will be able to see why it was killed. If it was memory pressure there would be a JetsamEvent log as well.
It is much more likely that your application is doing something "in the background" that it does not have a background mode or entitlement for. For example, it may be doing something past the background task assertion time limit, etc.
As far as your CPU and memory use, do not trust the gauges in Xcode. These are just an estimate and are often way off, and they do not capture the information you actually need (like dirty VM usage). Instead use Instruments.
https://www.reddit.com/r/iOSProgramming/comments/822id9/ideas_for_debugging_a_memory_leak_terminated_due/

Why is restart needed to send crash log on iOS?

With a custom crash reporting system (like the ones specialized at Ask the user to send crash log after crash on iPhone) to send the log, the app needs to restart. Why? Isn't there a possibility to send it during the custom exception handling? Or is there a crash reporting system that doesn't need to restart the app?
When a crash occurs the app is in a highly unstable state. So a crash reporting library can not do anything since even allocating memory at crash time may cause way more damage. So crash reporting SDKs can only use so-call async-safe C methods to collect all crash data. Any Objective-C code can not be processed either and also the iOS networking stack can not be used.
Please also note that exceptions are just one example of app crashes in Objective-C, there are also crashes triggered by low-level BSD signals. Both types mean that the app is in a highly unsafe and unstable state and as little code as possible should be invoked at crash time.
So this would require a rewrite of most of the networking frameworks to be able to send data out at crash time, and this may even not be possible to do in a safe way. That is why all proper crash reporting SDKs don't do anything like that.
In addition, on iOS it is not possible to create another process which could send the data in the background, so the only safe and possible solution is to send data the next time the app starts.
Now this has another conclusion that crashes that happen early on app startup might never be sent since the app is crashing before or while it sends. Some SDKs provide mechanisms to handle that scenario which most likely requires changes in your app startup code.
Since you app crashed there is no process running any more that you app controls, thus you can not start a new process to send the report.
Any code in the crash handler only has limited time to save what ever made you app crash before iOS kill whole app and removes it from memory.
When you restart you app the crash reporter formats the crash report and sends it. This can only be down when the when you app is active.

Resources