Crash on some devices when using GCD - crash

I have an iOS application that's crashing on a few devices. Given the bad reviews I see left on iTunes when this happens, the crashes appears to be happening at the same point in the code.
Finally, one nice person actually contacted me instead of just leaving a review, and they even when as far as to install a debug version of the app using TestFlight for me.
Armed with the crash report I can see that it occurs somewhere deep in malloc:
2 libSystem.B.dylib 0x34683d6e _sigtramp + 42
3 libSystem.B.dylib 0x3468c886 szone_malloc_should_clear + 2122
And, given the line number, it appears to happen at the point that I start a background task:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
UIImage *image = [self loadImage:path];
dispatch_sync(dispatch_get_main_queue(), ^{
I'm unsure which of those 3 lines the crash is happening on, so it's unclear if the crash occurs at the call to GCD itself, right at the start of the block's code, or somewhere in the block itself.
The stack trace ends up in the function which includes the code snippet above and not, it would seem, in the block itself. If the crash were in the async block, would the stack trace still include the call tree to the parent function? I'm currently working o n the assumption that the stack trace for crash inside the block wouldn't include the call the the parent function (since the block's being executed asynchronously in its own thread), so I think it's the call to GCD that's crashing.
I've tried using TFLog to find the exact moment of failure, but the logs aren't being recorded at all. I know the log calls are done correctly since on my development device I see the logs pop up in the TestFlight recorder, so it seems that the crash is perturbing this debug option.
Finally, TestFlight can't find an iOS version number for the iPhone 4 that this user's using - so I'm wondering if this is a Jailbroken device, and if it is could that possibly have an effect? (I've asked the user, no answer yet).
Note that this is all ARC code, so i'd be very surprised to discover that it's a memory management issue. It's also isolated to a few devices, but those devices crash at the same point every time.
Can anyone offer any insights or debugging suggestions (given that I don't have a crashing device myself).
Thanks,
Tim

I've solved this horrid bug.
It turns out that DISPATCH_QUEUE_PRIORITY_BACKGROUND is only available on 5.0 or later, and will crash on previous versions.
I had actually tested the app on an iPhone 3G running 4.2.1, but since that model doesn't support GCD at all that particular code path wasn't being run....

Related

Objective-C and applescript -> Timeout events & threads

I am on macOSX (Sierra), not iOS, Objective-C, Xcode9.
I have an application with implemented applescript classes, XCode compiles them for me. Whenever i call an applescript method from within an *.m file (and from a background thread!) i dispatch_sync it to the main thread (as applescript needs to be executed in the main thread) - sync cause i need the result to continue.
I'd like to show you with a simple example:
Applescript:
on openFile_filePath(filePath)
try
tell application "Adobe InDesign CC 2018"
set myDoc to open (filePath as string)
return id of myDoc
end tell
end
return 0
end
Objective-C
// Method is running in a background thread
// appleScriptHelper is properly instantinated
__block NSInteger docID = 0;
NSString* someFile = #"/Users/user/Desktop/";
dispatch_sync(dispatch_get_main_queue(), ^{
docID = [self.appleScriptHelper openFile:someFile];
});
This runs smooth - as long as InDesign responds! Sometimes, InDesign freezes and then my whole app freezes cause it basically waits forever on the main thread.
What i tried:
I cannot use a timer cause the main thread is blocked anyways and i cant pass a "cancel" message - cause Applescript is busy anyways waiting for something never happen.
In addition it is not possible to work with "with timeout of x seconds" in applescript when compiled from XCode (just doesnt work as mentioned in other posts).
I tried it with NSOperations but as i need to dispatch to the mainThread... still the same issue.
So my question is: Is there any way i can STOP the whole dispatch_sync block after a time of x seconds? Or is there any other possibility to keep the app running and not being locked up forever through InDesign freeze?
Note: The implementation works fine - please don't recommend 'use NSApplescript' or 'use Scripting Bridge'.
Reasons: ScriptingBridge - it's almost impossible to create a working HEADER file for InDesign (it almost weights 15 MB and throws tons of compiler errors - i did fix that once with lot of manual work just to see it not working anymore for the next Version of InDesign). NSApplescript is fine as long as you have simple scripts which is not the case.
Any help appreciated
Were NSAppleScript sufficient for your needs, I'd say use NSUserAppleScriptTask which runs scripts out of process with async completion callbacks. And yes, as you say, Scripting Bridge is utterly unfit for non-trivial automation, especially any involving large complex crusty Carbon apps like Adobe's, so don't waste a second on that.
There is AppleEventBridge/SwiftAE, but with Apple shuffling off the whole AS/AE infrastructure to quietly die off, I don't promote or support those any more, so maxima caveat emptor. (I still use Python appscript for my own Adobe app automation,btw, and it continues to blow everything else out the water, but I won't be surprised if the whole industry eventually goes Windows as the only professional-oriented platform left.)
..
The problem with using AppleScript-ObjC* is that AppleScript component (aka interpreter) instances are not thread-safe: you can instantiate them on any thread you like, but you can only use them on that thread, not from others. ASOC doesn't let you control any of this stuff for yourself; neither does NSAppleScript. (OSAKit does, but it's as painful to use as NSAppleScript is.) So ASOC code is de facto limited to running on the main thread only.
If you're stuck with using ASOC, I think your best bet is to push that code out into a subprocess that your main process talks to asynchronously via XPC Services or whatever. That'll avoid blocking your main process's main event loop (which then blocks its GUI) while allowing ASOC to do its own thing independently.
p.s. Another problem with ASOC is that changes in 10.13's bridgesupport files have changed/broken how C APIs are mapped to AS, which can break existing ASOC-based scripts. (I've stopped recommending ASOC unless/until that's fixed.)

How to get crash/hangs reports for applications, daemons and OSX programatically?

I know there is a way to get crashes and hangs for all applications. These files are placed in "/Users/user/Library/Logs/DiagnosticReports". So I could get version, time and name of the app.
But how to get daemon/process crashes and hangs? I need to know which exactly daemon was crashed/hanged and time when it happened.
Also is there is a way to get some system(OSX) crash with the same info?
Also would be great to get some resource failures/warnings: out of memory or out of disk space.
I need to get it programatically.
On Windows we can do this using NotifyChangeEventLog () API. All these info we can gather using such method. Also it notifies if something happened.
For the daemons crash/hang report see the "/Library/Logs/DiagnosticReports" directory. According to this document you can also find there kernel panic reports (i.e. system crash).
Don't know about NotifyChangeEventLog-like API, but in situations like "out of memory" there will be an exception, so you just need to catch it. See Error Handling Programming Guide for details. Also take a look at Exception Programming Topics
Edit: for the information about Crash Reporter take a look at Chapter 5 of Levin's book "Mac OS X and iOS Internals: To the Apple's Core"
in 10.9 the activity monitor offers you two tools when you have a hang but no crash hence no crash report:
spindump - memory dump like crash report and
sys digs which produces a bundle of files

No SystemOutOfMemoryException

My App suddenly crashes at one point (reproducible) when run on a 512mb phone emulator (only have a 920 to test). There wasn't any exception, it just went black. I then ran the analysis tool on the application and found out the memory reaches its limit at the point the app crashed. The app exits with an error code. The most recent one I found was 0x887a0005, but I'm pretty sure I saw another one a little time back. Sadly, I don't have that one anywhere.
I load about 600 images from the web into BitmapImages with the CreateBackground option, and handle the ImageOpened event.
I'm not asking for help managing the problem itself, I'll find a way to work around it. I'm just wondering why the App isn't throwing any exceptions, and instead just crashes. Any ideas her
This is expected behavior. Depending on which piece of code is executing at the very moment you run out of memory, an out of memory exception may be thrown - if one can be thrown by that specific .NET class or under laying class. But the operating system is not going to wait for this to happen, and will usually just terminate your app. It's not sending your app a "terminate" or "out of memory" signal, it just kills it.

Mac OS X: prevent the crash report window from appearing in my app

I'm developing an app on Mac OS X which is suspected to crash sometimes (well, not due to my app, but due to unstable third-party plug-ins it loads. This app actually acts as a crash firewall; many crashes can happen at startup, so no need to bug the user about it at this time).
Is there a way to prevent the crash report window from popping in front of the user?
Thanks!
PS: this is about this window, but not for WebKit:
I'm not aware of any really supported solution, but there are some (ugly) ways to achieve it.
First, you need to catch the signal yourself. I assume you know how to do that (see sigaction). Then within your crash signal handler, call _exit(). That's with a leading underscore. It's a faster, less safe version of exit(). This will typically avoid the crash reporter. I've used this in some C++ projects that had such flakey memory management that they often crashed on shutdown. I'm not proud of it; I'm just saying it works....
The other solution is to launch another second process during your crash handler. The second process waits around for CrashReporter to launch. When it does, kill it. The last time I tested this approach was 10.5. I don't know if 10.7 still launches the same kind of process to display that alert.
For a system-wide solution, read man ReportCrash. However this solution is not specific to an application.
Using cli Swift 4.2.1
Building on Rob Napier's answer.
I don't know how signal(3) becomes Darwin.signal(_:Int32,_:#convention(c)(Int32)->()) but the following actually works (preventing reporter for uncaught NSException), whereas temporarily doing and reverting defaults write com.apple.CrashReporter DialogType none && defaults write com.apple.CrashReporter UseUNC 1 (from osxdaily.com 2010 & 2015) (on my macOS 10.13) does not work.
import Darwin
signal(SIGABRT ){n in _exit(128+n)}
(Using Bash(1) signal exit(3) convention.)
Moving on, I find "Unexpectedly found nil"-errors (from implicit unwrapping in my case) uses another signal:
signal(SIGILL ){n in _exit(128+n)}
This also skips the builtin call stack printing and though it doesn't show where the nil's found anyway, a variant can be printed by the following:
import Darwin
import Foundation
Thread.callStackSymbols.forEach{fputs($0+"\n",stderr)}

App crashes on fast exit+restart

I am working with a free app that calculates grades for norwegian high school students. The different subjects are stored in a sqlite database. Everything works fine, except for one thing: If i close the app and restart quickly (faster than, say, one second), it crashes. Also, this only happens if I close the app in specific circumstances involving selecting/checking subjects in a UITableView (the changes are immediately stored in the database). Anyway if I wait for more than one second before restarting the app, it never crashes.
The error is not traced in any way in the console window.
Instruments has found some memory leaks in my app, but they are very small (16 bytes). I presume that is not the reason for the crash (but I will try to stop the leaks). I have also tried deleting and reinstalling the app, and turning the iPod/iPhone on and off. No change...
I understand that I cannot ask anyone to find the error in the extensive code of my app. My questions to you guys are:
Have any of you experienced similar errors? Related to sqlite?
Do you think App store will reject the app because of this?
Does anyone have any idea where to start looking for the error?
I am very thankful for any response!
When you say "it crashes," what is the actual error you get in the stack on the phone? Is it an actual crash, or are you getting a "failed to launch in time error?"
On iPhone, it's possible for an app's main thread to terminate while still running background nondetached threads. In this sense, despite all the claims that you cannot run in the background, you actually can... for a few seconds. When the main thread terminates, you go back to Springboard, and eventually the OS will kill your process if it doesn't terminate on its own. Do you manage any of your sqlite work on a background thread? Do you create any nondetached threads (this generally requires pthreads, so if you don't know, you probably aren't, but sqlite might; check in Instruments).
It's possible that your last instance still has a lock on your database, and that your re-launch doesn't react well to that lock. Do you have proper error handling around your open?