UA-17470720-3

Jump to content


Photo
- - - - -

Core Data Concurrency Violation in SCCoreDataStore

data-stores core-data bug

  • Please log in to reply
3 replies to this topic

#1 Laeger

Laeger

    Experienced Member

  • STV 5.0 Pro
  • PipPipPipPip
  • 59 posts
Reputation: 6
Good

Posted 22 December 2014 - 10:21 AM

Tarek,

I have come across what I believe is a bug with how SCCoreDataStore is implemented, with regards to multiple contexts.  I'll try to be general in my description, since I am not sure what source code I can and cannot post.

 

Outline:

SCCoreDataStore registers for NSManagedObjectContextWillSaveNotification's upon creation, but it does not specify an object to observe.  Thus, ALL NSManagedObjectContextWillSaveNotification's are received and handled by calling -willSaveContext.  This becomes a problem if there are any background context's that perform work (say, fetching from a remote data store) and then save, as the SCCoreDataStore will receive that notification and call -willSaveContext, which then calls -forceDiscardAllUnaddedObjects.  In addition to potentially discarding a still-valid object, it is possible that this creates a Core Data concurrency violation because the notification could have been sent by a background thread and thus received and handled on a background thread.  When -forceDiscardAllUnaddedObjects calls -discardUninsertedObject:, it could be doing so on a queue other than the object's managedObjectContext's queue, thus violating concurrency.

 

Fix:

To fix the issue, I did not want to modify your code if possible.  Thus I only added a method:

- (void)setManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
{
    if (managedObjectContext != _managedObjectContext) {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextWillSaveNotification object:_managedObjectContext];
        _managedObjectContext = managedObjectContext;
        // Register with managed object notifications
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willSaveContext) name:NSManagedObjectContextWillSaveNotification object:_managedObjectContext];
    }
}

 

So far this is working for me.  I am running through my app to verify.  As long as saves are performed using either -performBlock: or -performBlockAndWait:, the notification should be sent and handled on the correct queue.  Then any concurrency violation is a developer mistake (not using the -performBlock: methods).

 

Can you see any issue with the above fix?

Thank you Tarek,

Aaron

 


  • Adjuramum likes this

#2 TODD GARLAND

TODD GARLAND

    Experienced Member

  • STV 4.0 Pro
  • PipPipPipPip
  • 69 posts
Reputation: 21
Excellent

Posted 08 January 2015 - 02:38 PM

Aaron,

 

I believe this is the crux of my problem. Per chance can you tell me where you install the above method. In the Header File/App or the actual full code.

 

Thanks

 

TRG



#3 Laeger

Laeger

    Experienced Member

  • STV 5.0 Pro
  • PipPipPipPip
  • 59 posts
Reputation: 6
Good

Posted 08 January 2015 - 03:14 PM

Todd,

 

In "SCCoreDataStore.m", right before -willSaveContext:.

 

Hope that helps,

Aaron



#4 Laeger

Laeger

    Experienced Member

  • STV 5.0 Pro
  • PipPipPipPip
  • 59 posts
Reputation: 6
Good

Posted 25 March 2016 - 08:29 AM

Tarek,

For what it's worth this problem still exists.  I'm curious if anyone else uses something like MagicalRecord to set up multiple contexts for Core Data.  If so it's highly likely this issue will come up.

 

Also, I should note that I uncommented the registration for NSManagedObjectContextWillSaveNotification in init, as it now gets set when the managedObjectContext is set.







Also tagged with one or more of these keywords: data-stores, core-data, bug

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users