I have this stack trace in Fabric:
My question: From the crash log, is the function 'formatMessageAuthorName' the only cause for this EXC_BREAKPOINT crash? E.g., are there other possible causes for the crash apart from the code inside this function?
Here is my formatMessageAuthorName function:
private static func formatMessageAuthorName(firstname: String, lastname: String?=nil) -> String {
// Capitalise first character of firstname
var Cap_firstname = firstname
Cap_firstname.replaceRange(Cap_firstname.startIndex...Cap_firstname.startIndex, with: String(Cap_firstname[Cap_firstname.startIndex]).capitalizedString)
guard let lastname = lastname else { return Cap_firstname }
// if has lastname & first char, capitalise too and concat with firstname.
if let firstCharLastName = lastname.characters.first {
return "\(Cap_firstname) \(String(firstCharLastName).uppercaseString)."
} else {
return firstname
}
}
My assumption
The only clue that I know that will make the function crash is when 'firstname' is an empty string, it will crash here since it accesses invalid array index:
String(Cap_firstname[Cap_firstname.startIndex])
However, I'm still skeptical about this assumption, since I'm quite sure that 'firstname' is not empty (it's retrieved from server). I even tested it by logging into some user accounts that has this crash, and using that page (MessageViewController), but I never had the crash myself and firstname is shown correctly. It also seems to not be about iOS versions as I received crash from iOS 8, 9, and 10.
I have this crash a lot (>300) after my recent app update and I have no idea why as it never happens before, the code here does not change through the update, and I can never reproduce it with the effected users.
If the culprit can only be the code in this function, and no other possibilities (like multi-threading, Realm etc.), I can turn to focus on the server issues instead, like how 'firstname' might be an empty string. But still, I can't imagine how it could happen, since I already used those user accounts and never have this crash myself.
Thanks a lot.
EXC_BREAKPOINT is always triggered by executing a trap instruction of some sort(*) and the exception gets delivered directly to the thread that executed the trap instruction. So if you are seeing a crash report that says this thread with this stack got an EXC_BREAKPOINT, that means that thread really did to something that executed a trap instruction.
You could probably see this by looking at the crash address in your binary, you will see some kind of trap instruction there. The swift standard library uses trap instructions to signal various kinds of invalid access errors, and that code probably got inlined into the function that's crashing. So this makes sense of your example above.
(*) EXC_BREAKPOINT can also be used for data watches, but that's not what's happening here, and anyway they would still be delivered to the thread that accessed the watched data...
I've got Fabric installed in my app, with Crashlytics enabled via a simple Fabric.with([Crashlytics.self]) call in AppDelegate. Everything was working great, until I pulled in Realm. I have a dead-simple function;
class func listObjects() {
let realm = try? Realm()
if let realm = realm {
let objSet = realm.objects(TestObject.self)
print("Retrieved \(objSet.count) objects")
}
}
Calling the function actually works just fine, but I get an odd warning;
[Crashlytics:Crash] Warning: NSUncaughtExceptionHandler is '_ZZ34RLMInstallUncaughtExceptionHandlervEN3$_08__invokeEP11NSException' in '<...>/Frameworks/Realm.framework/Realm'
Has anyone come across this before?
I guess this is happening because Crashlytics checks whether the uncaught exception handler is overridden, because it is relying on that itself, but it is commonly misused for purposes where there would be less dangerous solutions. đ
Realm is using this for good reasons: we need to tear down open write transactions. While we are doing that, we still ensure to call the previously configured exception handler as you can see here. So Crashlytics won't loose it's ability to report any exceptions in your app.
I'm writing an iOS extension that extends NEPacketTunnelProvider in the NetworkExtension framework released in iOS 9. I'm running into a situation where iOS is killing the extension once hits 6MB of memory used.
In a regular iOS app, there are two ways to detect memory warnings and do something about it. Either via [UIApplicationDelegate applicationDidReceiveMemoryWarning:(UIApplication*)app] or [UIViewController didReceiveMemoryWarning]
Is there a similar way to detect memory warnings within an extension? I've searched up and down the iOS extension documentation but have come up empty thus far.
ozgur's answer does not work. UIApplicationDidReceiveMemeoryWarningNotification is a UIKit event and I haven't found a way to get access to that from an extension. The way to go is the last of these options: DISPATCH_SOURCE_TYPE_MEMORYPRESSURE.
I've used the following code (Swift) in a Broadcast Upload Extension and have confirmed with breakpoints that it is called during a memory event right before the extension conks out.
let source = DispatchSource.makeMemoryPressureSource(eventMask: .all, queue: nil)
let q = DispatchQueue.init(label: "test")
q.async {
source.setEventHandler {
let event:DispatchSource.MemoryPressureEvent = source.mask
print(event)
switch event {
case DispatchSource.MemoryPressureEvent.normal:
print("normal")
case DispatchSource.MemoryPressureEvent.warning:
print("warning")
case DispatchSource.MemoryPressureEvent.critical:
print("critical")
default:
break
}
}
source.resume()
}
I am not very familiar with the extensions API, however my basic hunch says that you can register any of your object as observers of UIApplicationDidReceiveMemoryWarningNotification from within that class:
NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationDidReceiveMemoryWarningNotification,
object: nil, queue: .mainQueue()) { notification in
print("Memory warning received")
}
Usually when I set lldb watchpoints, when they're hit, lldb says watchpoint hit old value: new value. However, I set a watchpoint on an address that seems to be getting written to inside a 3rd party library (libjpeg-turbo) and instead of the usual watchpoint hit, I'm seeing EXC_BREAKPOINT code=258, subcode=0xADDRESS.
In all cases, I can see that the subcode must be the address, as it's always equal to the address or close to the one I set the watchpoint to. Can anyone confirm this?
If I delete the watchpoint and keep going, lldb won't pause with EXC_BREAKPOINT. But what does the code mean and where can I find some offical documentation on this?
The exc_types.h doesn't give any detailed information on it.
For anyone who is interested in this question there is a nice article about the topic:
Understanding iOS Exception Types
In all cases, I can see that the subcode must be the address, as it's always equal to the address or close to the one I set the watchpoint to. Can anyone confirm this?
There is not much information in exception_types.h headers:
open -t /Applications/Xcode.app//Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/mach/exception_types.h
I can confirm that I always see EXC_BREAKPOINT to have address in subcode.
However other types in the header say that subcode can have different kinds of information:
#define EXC_EMULATION 4 /* Emulation instruction */
/* Emulation support instruction encountered */
/* Details in code and subcode fields */
We had to investigate on one Swift crash that produced: EXC_BREAKPOINT. In our case it boiled down to Swift type coercions. Both of the following cause EXC_BREAKPOINT on ARM devices:
func test_crash() {
let num = Int(DBL_MAX)
}
func test_crash_2() {
let num = Int(Double(0) / Double(0))
}
In both of these cases EXC_BREAKPOINT has a subcode with an address which is the address of sbrk instruction if you look at the assembly.
exc_types.h only has the architecture independent parts of the exception definitions. You need to look in the i386/arm subdirectories to find the architecture specific parts. If you are on Yosemite, the arm directory won't be in /usr/include/mach, you'll have to look for it in the iPhoneOS SDK inside of Xcode.app. Anyway, mach/arm/exception.h says:
#define EXC_ARM_DA_DEBUG 0x102 /* Debug (watch/break) Fault */
And as you suspect the subcode is the address of the access.
But lldb doesn't report bare exceptions if it recognizes the exception as implementing some higher level task. In this case, it should be reporting the stop reason as a watchpoint hit. For some reason it doesn't recognize this as your watchpoint. Is the subcode address exactly the same as the one reported by watch list?
I've been trying to use Corona SDK's Facebook API to post the score on the game I'm developing on facebook. However, I'm having a problem with it. During the first time I try to post to facebook, I get this error after login and user authentication:
NSURLErrorDomain error code -999
Then, it won't post on facebook. What are possible causes of this error and how can I address it?
By the way, I am not using webview on my app. Just the widget api and a show_dialog listener in my Facebook class.
The error has been documented on the Mac Developer Library(iOS docs)
The concerned segment from the documentation will be:
URL Loading System Error Codes
These values are returned as the error code property of an NSError
object with the domain âNSURLErrorDomainâ.
enum
{
NSURLErrorUnknown = -1,
NSURLErrorCancelled = -999,
NSURLErrorBadURL = -1000,
NSURLErrorTimedOut = -1001,
As you can see; -999 is caused by ErrorCancelled. This means: another request is made before the previous request is completed.
Just wanted to add here, when receiving a -999 "cancelled" the problem usually is one of two things:
You're executing the exact same request again.
You're maintaining a weak reference to your manager object that gets deallocated prematurely. (Create strong reference)
hjpotter92 is absolutely right, I just want to provide solution for my case. Hopefully it is useful for you as well. Here is my situation:
On log in page > press log in > pop up loading dialog > call log in service > dismiss dialog > push another screen > call another service --> cause error -999
To fix it, I put a delay between dismissing dialog and pushing new screen:
[indicatorAlert dismissWithClickedButtonIndex:0 animated:YES];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"HomeSegue" sender:nil];
});
It is strange that this issue happens on iOS 7 only.
I have faced the same error with Alamofire and it was because the certificate pinning.
The certificate wasn't valid anymore, so I had to remove it and add the new one.
Hope it helps.
In addition to what Ramon wrote, there is a third possible reason when receiving a NSURLErrorDomain -999 cancelled:
You cancelled the task while it was executing either by calling .cancel() on the datatask object or because you used .invalidateAndCancel() on the session object. If you are creating a custom session with a delegate, you should call .invalidateAndCancel() or .finishTasksAndInvalidate() to resolve the strong reference between the session and its delegate, as mentioned in the Apple Developer Documentation:
The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session. If you donât invalidate the session, your app leaks memory until it exits.
If you are wondering about this logging behaviour, I found the following explanation in the Apple Developer forums:
By way of explanation, back in iOS 10 we introduced a new logging system-wide logging architecture (watch WWDC 2016 Session 721 Unified Logging and Activity Tracing for the details) and lots of subsystem, including CFNetwork, are in the process of moving over to that. Until that move is fully finished youâre going to encounter some weird edge cases like this one.
I didn't use Corona SDK's Facebook API but I encountered this problem when using Alamofire, the secondRequest always cancel in execution with the error -999, according to the posts I found on internet, the reason is that session property is deinit before completion of async work since it is out of the scope, I finally solved this problem by deinit the session property manually so the compiler won't deinit it at wrong position:
class SessionManager {
var session:SessionManager?
init() {
self.session = SessionManager(configuration:URLSessionConfiguration.ephemeral)
}
private func firstRequest() {
guard let session = self.session else {return}
session.request(request_url).responseData {response in
if let data=response.data {
self.secondRequest()
}
}
private func secondRequest() {
guard let session = self.session else {return}
session.request(request_url).responseData {response in
if let data=response.data {
self.secondRequest()
}
//session will no longer be needed, deinit it
self.session = nil
}
}
Our company's app has many -999 error in iOS. I have searched around, find the reason has two, like the network task has been dealloc or the certificate isn't valid. But I have checked our code, these two aren't possible. I am using Alamofire
which is using URLSession. Luckily, our company's android app's network is normal. So we check the difference. We found the http request from iOS is Http2.0, while android is Http1.1. So we force the backend http support version down to http1.1, then -999 error count descends!!!
I think there maybe some bug in Apple's URLSession. Check the link New NSURLSession for every DataTask overkill? for some detail thoughts
Please check If you call cancel() on URLSessionDataTask to fix
NSURLErrorDomain Code=-999 "cancelled"
I was getting this error in iOS specific version of Xamarin app. Not sure the underlying cause, but in my case was able to work around it by using post method instead of get for anything passing the server context in the request body -- which makes more sense anyway. Android / Windows / the service all handle the GET with content, but in iOS app will become partially unresponsive then spit out the 999 NSUrlErrorDomain stuff in the log. Hopefully, that helps someone else running into this. I assume the net code is getting stuck in a loop, but could not see the code in question.
For my Cordova project (or similar), turns out it was a plugin issue. Make sure you're not missing any plugins and make sure they're installed properly without issue.
Easiest way to verify this is simply to start fresh by recreating the Cordova project (cordova create <path>) along with the required platforms (cordova platform add <platform name>) and add each plugin with the verbose flag (--verbose) so that you can see if anything went wrong in the console log while the plugin is being downloaded, added to project and installed for each platform (cordova plugin add cordova-plugin-device --verbose)
Recap:
cordova create <path>
cordova platform add <platform name>
cordova plugin add cordova-plugin-device --verbose
For my case, I used an upload task post that did not need body contents:
// The `from: nil` induces error "cancelled" code -999
let task = session.uploadTask(with: urlRequest, from: nil, completionHandler: handler)
The fix is to use zero byte data instead of nil,
let task = session.uploadTask(with: urlRequest, from: Data(), completionHandler: handler)
The framework documentation doesn't specify why the from bodyData is an optional type, or what happens when it is nil.
We solved this problem by reloading the web view when it failed loading.
extension WebViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
webView.reload()
}
}