Earlier this week I tweeted about Core Data crash reports that I haven't been able to figure out. In fact, almost all of Twitterrific's reports were from Core Data. I assumed I was doing something wrong somehow but didn't know how to figure it out since I couldn't reproduce it.
These crash reports have been plaguing me for a long time. Years, probably. I've come to mostly ignore them assuming there was nothing I could do about them. I've asked a few times on Twitter and Googled a bit over that time, but nothing ever turned up.
This week, there was a breakthrough. Specifically, three people used the TestFlight feedback mechanism to report a crash that iOS had reported. They noted the app was in the background at the time. I had long suspected that was the case with this bug, but I was missing something.
Rather than look at the crash reports inside Xcode's Organizer, like I usually do, I happened to download the report attached directly to one of those feedback reports and take a look at it. It matched the typical Core Data crashes I see all the time in Organizer. No surprise.
I was about to close the log in defeat when I noticed that the Termination Reason was something unfamiliar. Xcode's Organizer does not report termination reasons on the crash reports - after all, one would normally assume the reason it was terminated was BECAUSE IT CRASHED, DUH!
Here's the thing - that assumption is totally wrong. iOS routinely terminates apps for all sorts of reasons like using too much memory or taking too long to do background processing or whatever. I don't know why this isn't included in Xcode's Organizer.
Naturally the termination reason in the raw crash log isn't some nice easily human-readable message - no, it's a hex code and a cryptic string that maybe suggests which subsystem is responsible for it. Why make anything easy for the developers, right?!
In this Core Data crash report the termination reason was: Namespace RUNNINGBOARD, Code 0xdead10cc. This was something I could Google. I found a few posts with it, although in many cases this hits were crash reports and no one noted the significance of the termination reason.
I found Tech Note 2151: developer.apple.com/library/archiv… and there it was way at the bottom under Other Exception Types: "The exception code 0xdead10cc indicates that an application has been terminated by the OS because it held on to a file lock or sqlite database lock during suspension."
Holy crap! I've been searching for this for ages and here, finally, is a clue! So I start looking around in the code now that I know what sort of trigger to look for. I find that there were cases where I wasn't asking for more background time before starting certain operations.
What was happening was, the app was sometimes closed while it was still doing some kind of network download and iOS was leaving it running in the background long enough for the network request to finish - but not long enough for the database processing and saving to finish.
Due to incorrectly placed task markers, the background task would be marked done before it had finished saving the database. When things happened in the wrong sequence, iOS would unceremoniously murder the process immediately - making it look like it had crashed inside Core Data.
I spent several days reworking a bunch of really old code to ensure task markers were being created and ended in the proper sequence and to ensure that the task wasn't marked as ended until after the *entire* process was done. Lo and behold, this appears to have worked!
So there you have it - another exciting tale of me doing things wrong for years! Remember kids, I'm a professional!
• • •
Missing some Tweet in this thread? You can try to
force a refresh
Feeling way better today now that the 2nd shot vaccine side effects have apparently wore off. I wonder if they will find ways to improve future versions to fix that?
I suspect the way these vaccines work is going to totally change medicine in the long run. Reprogramming your own cells to make the drugs you need is genius and feels like it’s one step closer to a true medical tricorder where the doc programs up the prescription and injects.
(If you didn’t know, that’s roughly how these mRNA vaccines work as I understand it - they contain RNA instructions that your own cells then blindly “run” which causes them to build a key part of the virus itself that your immune system then learns to attack and defend against.)
I may have figured out our auto-renewing subscription problem with Twitterrific. This should probably be a blog post, but I don’t want to commit to it being fixed yet - however I want to describe what I found in case it helps anyone or brings anything else to light. Lucky you!
Twitterrific implements client-side receipt validation - which is hard. Server-side looks like it's probably easier to deal with, but at the time this seemed to make more sense and we've just kind of stuck with it over the years.
Since this is hard to do, we did what pretty much everyone has likely done and found some open source code on GitHub that interfaced with OpenSSL to do the actual receipt validation. This code also had some methods to verify if a receipt record is an active subscription or not.