Core Data lightweight migration crashes after App update - iphone

Two days ago I released the App. According to feedback on AppStore and crash reports from itunesconnect there are a lot of crashes on launch. But not 100% users suffered, only 30% maybe.
I've read the crash logs and saw a problem. It's crashing on DB migration process. I use lightweight migration of database.
Usually I add new datamodel version very carefully. Even before each release I install a previous version of the App, use it for some time and only then I install the latest version above it. So was this time.
I looked through two datamodels (previous and present). Were added:
1) New entities (it's OK for lightweight migration)
2) New fields inside existing entities. All they are optional. (OK for lightweight migration)
3) One new field in existing entity which I made optional AND indexed. (OK?)
None of existing fields and entities were renamed.
What I did wrong?
Stack trace:
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0:
0 libsystem_kernel.dylib 0x352f439c pread + 20
1 libsqlite3.dylib 0x30d2d632 unixRead
2 libsqlite3.dylib 0x30d4221a readDbPage
3 libsqlite3.dylib 0x30d41156 sqlite3PagerAcquire
4 libsqlite3.dylib 0x30d583be moveToChild
5 libsqlite3.dylib 0x30d8e0e8 moveToLeftmost
6 libsqlite3.dylib 0x30d59582 sqlite3BtreeNext
7 libsqlite3.dylib 0x30d54328 sqlite3VdbeExec
8 libsqlite3.dylib 0x30d4f6c2 sqlite3_step
9 CoreData 0x329e8e2e _execute
10 CoreData 0x329e8d64 -[NSSQLiteConnection execute]
11 CoreData 0x32a8bd54 -[NSSQLConnection prepareAndExecuteSQLStatement:]
12 CoreData 0x32add63c -[_NSSQLiteStoreMigrator performMigration:]
13 CoreData 0x32ad42b8 -[NSSQLiteInPlaceMigrationManager migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:]
14 CoreData 0x32a79c02 -[NSMigrationManager migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:]
15 CoreData 0x32ac5bf4 -[NSStoreMigrationPolicy(InternalMethods) migrateStoreAtURL:toURL:storeType:options:withManager:error:]
16 CoreData 0x32ac519c -[NSStoreMigrationPolicy migrateStoreAtURL:withManager:metadata:options:error:]
17 CoreData 0x32ac6b58 -[NSStoreMigrationPolicy(InternalMethods) _gatherDataAndPerformMigration:]

Any chance that those users were more than one .xcversion back? Core Data will not "chain" your upgrades for you. So if you have V1, V2, and V3, and V3 becomes the current version, anyone at V1 will not be upgradable. It is possible to add in your own code that helps "step it through" V1 to V2, then V2 to V3. I believe Marcus Zarra's "Core Data" book had example code that does that.

If this was V3 of the data model, you need to also include the V1 and V2 xcdatamodel with the shipped app, in case some of your users are still on V1 and never upgraded to V2. It kind of sounds like you had a V1 data model, but didn't include it - but I'm not sure, you may simply be talking about other apps where you've done this.
Additionally, you'll notice that Xcode does not manage an ordered list of data models, you can only choose which one is the current one. It cannot automatically upgrade V1->...->Vm->Vn, because it doesn't know anything about the order between old versions, simply that they need to become Vn to work. Try poking around in the xcdatamodeld package with a text editor.
If you're relying solely on behavior provided by Core Data, all of your prior versions must be able to directly migrate to the latest, whether that is inferred mapping models, or by you including explicit mapping models: from V1->Vn, V2->Vn, ..., Vm->Vn. That's why some people write their own code to manage this.
I believe this is exactly what Scott described in his answer.
During development of our app, we created ~6 versions of the data model (we took all but the latest out before shipping v1 to the App Store). I found it very helpful to write unit tests that verified that Core Data could create an inferred mapping model, and that lightweight migration would work.
To do this:
NSURL *sourceURL = /* exercise for reader */, *destinationURL = /* exercise */;
NSManagedObjectModel *source = [[NSManagedObjectModel alloc] initWithContentsOfURL:sourceURL];
NSManagedObjectModel *destination = [[NSManagedObjectModel alloc] initWithContentsOfURL:sourceURL];
NSError *mappingError;
NSMappingModel *inferred = [NSMappingModel inferredMappingModelForSourceModel:source destinationModel:destination error:&mappingError];
At the end of this code block, you can assert that inferred != nil, and if it is nil you can print some helpful information by inspecting mappingError.
You may find this helpful to debug your problem. You might move the repetitive parts into a function that takes two strings, the filename of an old data model, and the filename of the latest.

Related

EF6/Code First: Super slow during the 1st query, but only in Debug

I'm using EF6 rc1 with Code First strategy, without precompiled views and the problem is:
If I compile and run the exe application it takes like 15 seconds to run the first query (that's okay, since I'm still working on the pre-generated views). But if I use Visual Studio 2013 Preview to Debug the exact same application it takes almost 2 minutes BEFORE running the first query:
Dim Context = New MyEntities()
Dim Query = From I in Context.Itens '' <--- The debug takes 2 minutes in here
Dim Item = Query.FirstOrDefault()
Is there a way to remove this extra time? Am I doing something wrong here?
Ps.: The context itself is not complicated, its just full with 200+ tables.
Edit: Found out that the problem is that during debug time the EF appears to be generating the Views ignoring the pre-generated ones.
Using the source code from EF I discovered that the property:
IQueryProvider IQueryable.Provider
{
get
{
return _provider ?? (_provider = new DbQueryProvider(
GetInternalQueryWithCheck("IQueryable.Provider").InternalContext,
GetInternalQueryWithCheck("IQueryable.Provider").ObjectQueryProvider));
}
}
is where the time is being consumed. But this is strange since it only takes time in debug. Am I missing something here?
Edit: Found more info related to the question:
Using the Process Monitor (by Sysinternals) I found out that there its the 'desenv.exe' process that is consuming tons of time. To be more specific its consuming time with an 'Thread Exit'. It repeats the Thread Exit stack 36 times. I don't know if this info is very useful, but I saved a '.cvs' with the stack, here is his body: [...] (edit: removed the '.cvs' body, I can post it again by the comments if someone really think its going to be useful, but it was confusing and too big.)
Edit: Installed VS2013 Ultimate and Entity Framework 6 RTM. Installed the Entity Framework Power Tools Beta 4 and used it to generate the Views. Nothing changed... If I run the exe it takes 20 seconds, if I 'Start' debugging it takes 120 seconds.
Edit: Created a small project to simulate the error: http://sdrv.ms/16pH9Vm
Just run the project inside the environment and directly through the .exe, click the button and compare the loading time.
This is a known performance issue in Lazy (which EF is using) when the debugger is attached. We are currently working on a fix (the current approach we are looking at is removing the use of Lazy). We hope to ship this fix in a patch release soon. You can track progress of this issue on our CodePlex site - http://entityframework.codeplex.com/workitem/1778.
More details on the coming 6.0.2 patch release that will include a fix are here - http://blogs.msdn.com/b/adonet/archive/2013/10/31/ef6-performance-issues.aspx
I don't know if you have found the solution. But in my case, I had similar issue which wasted me close to a week after trying different suggestions. Finally, I found a solution by changing my web.config to optimizeCompilations="true" and performance improved dramatically from 15-30 seconds to about 2 seconds.

RestKit ObjectLoader Unrecognized Selector trying to map objects

This issue is specific to RestKit, but I believe the underlying issue is related to registering to notifications. I could really use some help figuring this one out...I seem to be having the same issue appearing multiple times:
An NSInvalidArguementException coming from
serviceDidBecomeUnavailableNotification within RKClient. The action
is calling from __NSMallocBlock__, __NSCFString, __NSCFArray, NSURL,
and UICFFont... obviously the delegate is not being set correctly.
It is ONLY in my requests using RKObjectMapping to map the response to
my model classes. I've noticed the objectLoader has
isResponseMappable and checks [self.response isServiceUnavailable] -
which then posts a RKServiceDidBecomeUnavailableNotification. This
seems to be where my issue is coming from. The only place I see
isResponseMappable being called is within didFinishLoad:(RKResponse*)response.
Here's an example stack trace, I thought this could be very beneficial:
Error Message:
NSInvalidArgumentException: -[__NSMallocBlock__
serviceDidBecomeUnavailableNotification:]: unrecognized selector sent
to instance 0xee168b0
CoreFoundation:2:in `0x37d4dacb -[NSObject doesNotRecognizeSelector:]
+ 174'
CoreFoundation:3:in `0x37d4c945 ___forwarding___ + 300'
CoreFoundation:4:in `0x37ca7680 _CF_forwarding_prep_0 + 48'
Foundation:5:in `0x31c6f50f __57-[NSNotificationCenter
addObserver:selector:name:object:]_block_invoke_0 + 18'
CoreFoundation:6:in `0x37d16577 ___CFXNotificationPost_block_invoke_0
+ 70'
CoreFoundation:7:in `0x37ca20cf _CFXNotificationPost + 1406'
Foundation:8:in `0x31be33fb -[NSNotificationCenter
postNotificationName:object:userInfo:] + 66'
Foundation:9:in `0x31be4c2b -[NSNotificationCenter
postNotificationName:object:] + 30'
MyApp:10:in `0x000d2157 -[RKObjectLoader isResponseMappable] + 114'
MyApp:11:in `0x000d2b83 -[RKObjectLoader didFinishLoad:] + 418'
MyApp:12:in `0x000cb151 -[RKResponse connectionDidFinishLoading:] +
36'
Foundation:13:in `0x31ca6c39 __65-[NSURLConnectionInternal
_withConnectionAndDelegate:onlyActive:]_block_invoke_0 + 16'
Foundation:14:in `0x31bfe6e9 -[NSURLConnectionInternalConnection
invokeForDelegate:] + 28'
If anyone has any helpful tips, ideas, or suggestions on how to debug this, it would be greatly appreciated! I've been dealing with this for two weeks and am only seeing it in deployed apps (cannot replicate the issue) so any insight is better than none! Cheers!
Check whether you have add all the frame works recommended for RestKit, in your project
1. **CFNetwork.framework**
1. **CoreData.framework**
1. **MobileCoreServices.framework**
1. **SystemConfiguration.framework**
1. **libxml2.dylib**
Just incase any others fall onto this solution, the approach I took was:
Completely remove RestKit from my existing project. I then downloaded the master branch of RestKit, reintegrated into my project (there were some deprecated methods, less necessary frameworks, and refactored classes, but all in all pretty simple). I will be releasing this version with the new RestKit within the next week or so, and HOPE to not see this issue arising again.:)
If I do have this issue, I will come back and modify my answer with a reason for why it's still happening.

CoreData lightweight migration failing on iOS

I'm trying to migrate my core data data to a new version. The only change I've done is adding one field (NSString *sessionId)
So what I've done:
1. Create version 2 of my core data file
2. Add sessionId in this file.
3. set version 2 as default.
4. add sessionId in Offer.m and .h
5. When initializing the persistentStoreCoordinator adding the options:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
When Im starting my application when i thought it would get the updated model i get:
Unresolved error Error
Domain=NSCocoaErrorDomain Code=134130
"The operation couldn’t be completed.
(Cocoa error 134130.)"
UserInfo=0x7643200
{URL=/Users/ei/Library/Application
Support/iPhone
Simulator/4.0.2/Applications/81B816AE-5CA0-46DB-83E7-6A765EBF9D05/Documents/Offers.sqlite, metadata={type = immutable dict,
count = 7,
Followed by
reason=Can't find model for source store
I get the same error if I don't set the options when loading the persistentStoreCoordinator
What is it I am missing?
Apparently, if you merge two models and then try to automatically migrate from one model to another doesnt work. We ended up separating them.
The error message means exactly what it says: it's missing the .xcdatamodel (or strictly .mom) that the database was saved with. I'd try grabbing the .xcdatamodel from an old revision and seeing if there have been accidental changes.
Another problem is that Xcode isn't good at deleting files which are no longer being built, both when building and when installing (Xcode is allowed to do "incremental installs" to make development quicker, and at least in previous versions, never deleted files). Instead of building MyApp.app/MyModel.mom, it's now building MyApp.app/MyModel.momd/MyModel.mom, but the old MyModel.mom might stick around and confuse whatever you're using to load the model (usually it complains about being unable to merge models, though...). The fix is to nuke the build directory and install the app using OTA/iPhone Configuration Utility/iTunes (in order of user-friendliness), and is incidentally why I tell Xcode 4 to stick build products in the project dir (the reason why they changed it is presumably because people aren't smart enough to not commit it...).

Strange Core Data crash with _Unwind_SjLj_Resume after migrating

I am getting a strange crash from some of my beta testers that I am having trouble with. The symbolicated crash reports indicate that the crash is occurring in the simple allocation of a controller as a singleton, at the init call, but according to the stack trace, it appears that the code I have in init is not actually where the crash is. Here is the relevant code:
1534| + (UA[REDACTED]PlayerController*)sharedInstance
1535| {
1536| #synchronized(self)
1537| {
1538| if (sharedInstance == nil)
1539| sharedInstance = [[UA[REDACTED]PlayerController alloc] init];
1540| }
1541| return sharedInstance;
1542| }
This has never crashed before, and the code has not changed anytime recently. Here is the raised stack trace:
Thread 5:
0 libSystem.B.dylib 0x33bd52d4 __kill + 8
1 libSystem.B.dylib 0x33bd52c4 kill + 4
2 libSystem.B.dylib 0x33bd52b6 raise + 10
3 libSystem.B.dylib 0x33be9d26 __abort + 62
4 libSystem.B.dylib 0x33be9d7e abort + 62
5 libSystem.B.dylib 0x33bd7980 __assert_rtn + 152
6 libgcc_s.1.dylib 0x32acab4e _Unwind_SjLj_Resume + 26
7 [REDACTED] 0x00060b64 +[UA[REDACTED]PlayerController sharedInstance] (UA[REDACTED]PlayerController.m:1540)
8 [REDACTED] 0x00063e6c -[UA[REDACTED]PlayerViewController setupControlViews] (UA[REDACTED]PlayerViewController.m:224)
9 [REDACTED] 0x00062ce0 -[UA[REDACTED]PlayerViewController viewDidLoad] (UA[REDACTED]PlayerViewController.m:268)
10 UIKit 0x320a0270 -[UIViewController view] + 104
…
Any ideas as to what this cryptic crash is and where it might be coming from?
UPDATE 1
It appears it has to do with core data and migrations. I was able to duplicate it, but the root cause is still unknown. I have some automatic migrations that are in this version, and it appears that while some of the NSManagedObjects can be read, others are throwing this exception, particularly on a NSManagedObjects relationship. It might not be related to the PlayerController at all. Any Core-Data experts have some insight?
UPDATE 2
Here is the call stack of the crash after I have found a way to reproduce it
and the relevant code:
if (resultArray && [resultArray count]) {
for (MixAudio *ma in resultArray) {
Audio *audio = [ma valueForKey:LOCAL_MIX_AUDIO_AUDIO_KEY];
if (audio) {
[returnArray addObject:audio];
}
}
To help explain what I did to reproduce it, I have to explain the data structure a little. I have Mix and Audio items. Mixes have many Audio, Audio belongs to many Mixes. This is a simple relationship call on the MixAudio objects to get the Audio. Now, this has only been crashing here after I do a database restore to the new version.
Database backups in my setup means zipping up the database to save the data, then unzipping on restore. This crash only happens after the restore process. To make things more complicated, there are 3 database versions with mapping models. Because this process worked for me before the versioning, I feel that something in my versions is causing this crash.
All other data is fine and can be accessed, even saved. Somehow, this single fetch is causing issues. There are no errors or warnings when setting up the persistent store or managed object model. Furthermore, new Mix objects can be created and accessed fine, only older fetches (that were in the DB before the restore) are failing.
If I don't catch the error, the console prints:
Assertion failed: (_Unwind_SjLj_Resume() can't return), function _Unwind_SjLj_Resume, file /SourceCache/libunwind/libunwind-24.1/src/Unwind-sjlj.c, line 326.
Putting a try/catch around the crashing line allows me to inspect the root crash cause:
Error: NSRangeException: *** -[NSMutableArray objectAtIndex:]: index 4294967295 beyond bounds [0 .. 16]
but this makes no sense (to me at least) for a simple valueForKey call. 4294967295 = 2^32-1 which means the index var was probably set to −1 if that helps. I am lost here.
[SOLVED] UPDATE 3
I was right about it being in the versioning :) I reread the section on versioning in Zarra's book and had a major DOH moment. This is the first time I have ever had an app with 3 database versions. I am using Mapping Models in my app and I naively assumed that core data would be able to map from 1-2 using one model, then 2-3 using the next. I literally hit my head when I realized I did not have a 1-3 mapping model. to test it out, I added one quickly and everything is as smooth as butter. Now I just have to go back and use his Progressive Data Migration samples to make my life easier as I go on with more version of this DB.
I am hoping Zarra drives by here and answers something… anything… so I can give him the points for this :)
While the OP was able to solve his own question, it is helpful to have a clear understanding of migrations.
When you create a second version of your data model, you need a mapping model from version one to version two.
When you create a third model you need a mapping model from one to two AND a map from one to three.
When you add a fourth model you need the following models:
1-2
1-3
1-4
2-3
2-4
And it gets more progress from there.

iTunesConnect crashlog is partially symbolicated; does not show line numbers

The crashlog on iTunesConnect for my XCode 3.2.5-built application shows method names, but not line numbers. For example, in the abridged crash report I've pasted in below, it shows this:
0x000f5ef8 -[MyTableViewController dealloc] + 120
There are two things here that are puzzling me, upon which I'd appreciate some insight. The first is why the raw .crash file coming from iTunesConnect is already partially symbolized: it shows the class and method name, but not the source code file and line number. I would expect the raw iTunesConnect crashlog to show just the hexidecimal addresses. As I understand it, only once I download the crash log onto my local system and explicitly bind it using the appropriate tool (XCode Organizer, symbolicatecrash, atos, gdb x/i command, etc) and to the exact application binary and dSYM files (those having the matching UUID), will I see the full symbols of class, method, source code file, and line number. Even when I download and view the crashlog on a Windows box, it appears partially symbolized. I am concerned that my distribution binary must be including some debug symbols in order for this information to show up in the raw crashlog, despite having "Strip Linked Project" set in its Distribution target settings. Any insight here would be great.
The second thing that is perplexing me, and is of more immediate concern to me in fixing this high-profile crash, is this business of the offset. I've very carefully located the dSYM and application binary with the matching UUID, put them in my home directory so they can be found by Spotlight et al, and no matter what I do, I am unable to convert that offset [MyTableViewController dealloc] + 120 to a source code file (which is known to me to be MyTableViewController.m) and a line number. I have tried the following tricks with the raw iTunesConnect .crash file:
XCode Organizer: its "symbolication" affects no changes to the crashlog -- it's the same.
symbolicatecrash: It doesn't really complain about anything in verbose mode, and the output crashlog is the same
gdb: Using the same gdb and -arch setting that XCode 3.2.5 uses for producing the distribution build, and loading in the matching application binary and dSYM symbols per this post, gdb 'x/i' and 'info line *' commands tells me that [MyTableViewController dealloc] + 120 corresponds to a totally unrelated piece of our codebase in a completely different file -- a .h file, even! Wild goose chase.
Something is not right here. Even despite ensuring the exact same UUID across the crash report, the application binary, and the dSYM file ... none of these tools can yield an actual line number, and doing it the low-level way sends me on a wild goose chase. Knowing the exact line number is critical to fixing this, because we are unable to reproduce this crash in-house so we're flying blind here. This looks to be a simple over-released object, but it's not clear which exact object it is, and we're unable to tell from context. I'm wondering if there is some misappropriated XCode build setting that is somehow breaking the symbolication process.
Thanks for your time!
What follows is the abridged raw .crash log from iTunesConnect.
Incident Identifier: 09EAE058-7D55-4AE5-947A-17280FB0211A
Hardware Model: iPhone3,1
Process: MyApp [1895]
Path: /var/mobile/Applications/B4B872EF-CB0D-41D7-A7B5-435ADE479D0A/MyApp.app/MyApp
Identifier: MyApp
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2011-01-24 14:06:32.941 -0500
OS Version: iPhone OS 4.2.1 (8C148)
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0xd0000000
Crashed Thread: 0
Thread 0 Crashed:
0 libobjc.A.dylib 0x33479466 objc_msgSend + 18
1 MyApp 0x000f5ef8 -[MyTableViewController dealloc] + 120
2 CoreFoundation 0x33a26f74 -[NSObject(NSObject) release]
3 libobjc.A.dylib 0x3347a812 objc_setProperty
4 UIKit 0x320bb4a0 -[UINavigationController setDisappearingViewController:]
5 UIKit 0x320bb478 -[UINavigationController _clearLastOperation]
xx SNIP xx
23 MyApp 0x00014eac main + 36
24 MyApp 0x0000b324 start + 44
XX SNIP xx
Binary Images:
0x1000 - 0x1e3fff +MyApp armv7 <5570f8eee3bc11647732c12f96fe9553> /var/mobile/Applications/B4B872EF-CB0D-41D7-A7B5-435ADE479D0A/MyApp.app/MyApp
I've experienced similar issues with releasing object that weren't retained or that were in an autorelease pool thereby getting released twice. More often than not I'll get a crash for a location that is inside the framework/iOS but was caused from my lack of proper memory management. I'm not saying this IS happening here, but just is something I've experienced when a similar error has presented itself.