Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

About XMPPRosterStorage mainThreadManagedObjectContext will let app die question #340

Open
leolicai opened this issue Mar 23, 2014 · 16 comments

Comments

@leolicai
Copy link

Hi, Every body!

There is a very bad problem. if our custom view controller use XMPPRosterStorage mainThreadManagedObjectContext to UIFetchResultsController auto refresh our friends list in a table view. then if xmppStream have received a iq:roster message.
The app will die.

I think the have dispatch_sync() call two times use one queue flag.

Anybody have the solution? I ask use xmppframework friend.
nobody can fix it!

Thanks

@ObjColumnist
Copy link
Collaborator

Have you init your modules using the main queue rather than another queue e.g. High Priority Queue?

@bladebunny
Copy link

This seems to be a duplicate of issue #336.
I'm seeing the same issue and have spent hours trying to troubleshoot it.

  • Have tried initing my stream XMPPRosterStorage object with get_main as well as with the default background queue as well as custom concurrent queues.
  • I've also tried using the default main context (and ensuring I'm calling from main).

Though I don't quite know the fix, I've isolated the failure point to be in XMPPCoreDataStorage. Calls to get the context call down to the PersistentStore coordinator getter.

Inside the getter, at the very bottom, last if/else. On first run of the app, I generally hit the if block and get a valid context back (the if condition executes block()). On pretty much every other attempt to access the context, I hit the else condition which tries to call dispatch_sync(storageQueue, block); at this point the call just hangs. I haven't seen it actually crash but that's because it hangs so badly on this call that I generally just have to kill the simulator -- have not yet tried it on the phone.

I have read and re-read the CoreData notes on the project Wiki and I am reasonably certain I am not running afoul of any of its cautions.

That said, I have no idea what I did, but in my initial implementation I had it actually working but since then (yesterday afternoon) I'm getting this behavior. Have even refactored my code to pretty much follow the iPhoneXMPP example line but line and still see this behavior. I'm on the point of just removing the core data backing altogether, which would be a shame as it seems to be an excellent capability to be able to use and I don't relish having to write all the roster storage stuff myself.

I know this is an Open Source project but a little more info/documentation on the various ways to use some of the storage mechanisms and/or how to write your own provider would be much welcome.

Aside from that, it's a lovely framework and I look forward to using it on my current project.

@bladebunny
Copy link

A possibly related issue (I can create a new issue if need be). Even though I am targeting SDK 7.0 and using ARC -- I keep hitting this conditional in GCDMulticastDelegate - > initWithDelegate:

#if !OS_OBJECT_USE_OBJC
if (delegateQueue)
dispatch_retain(delegateQueue);
#endif

I am hitting the dispatch_retain call - which I believe is invalid in ARC -- and crashing there.

In fairness, I am using CocoaPods to manage XMPPFramework as a dependency.
Is there some additional flag I should be setting? I would have expected OS_OBJECT_USE_OBJC to be false and thus not hit the dispatch_retain. As far as I can tell, no other pods are setting this nor is my main project/target. And no other pods, such AFNetworking, seem to be hitting this condition. Strange.

@ObjColumnist
Copy link
Collaborator

In regards to the NSFetchedResultController issues, if anyone wants to provide a sample of it locking up il be happy to take a look at it.

@bladebunny
Copy link

I'll see if I can put together a reproducible sample later today or first thing tomorrow.

@bladebunny
Copy link

Here's an example of how I'm using it.
https://github.com/bladebunny/xmppf-psc-problem.git

Of course, its all working fine here - except for using privates queues as noted above -- that repros or I am doing it wrong (probably the latter).

The actual project we're using this in has its own Core Data stack - so it seems as though something is blocking CoreData retrieving the PSC when getting the main context as noted in my first comment above.

@leolicai
Copy link
Author

Hi.
I push my test project on a github
https://github.com/leolicai/xmpptest.git

you can try it.

before start the project. please set the iPhone Simulator -> restore content and setting.
Then run the app. open the setting page.

look the console. please notice the output log. when all connect is done.
click the my friends cell.

the app will halt!!!

most of time the first run the app will show these status.

if you click my friends cell when some data not close connect . it can enter the my friends page.

thanks a lot!

@ObjColumnist
Copy link
Collaborator

@leolicai It seems to block on allowRosterlessOperation but if I init XMPPRoster with the high priority queue it appears to go away:

_xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:_xmppRosterStorage dispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];

Do you see the same thing?

@leolicai
Copy link
Author

@ObjColumnist Thanks man!
Use dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) looks ok.
The app running ok.
It's my usage error?
I just read the xmppframwork example.
Thanks a lot.

@ObjColumnist
Copy link
Collaborator

I don't think its should break if you specify NULL for a queue (as it creates its own) but there appears to be a deadlock when the XMPPRosterCoreDataStorage calls back into XMPPRoster.

@yindongwang
Copy link

@ObjColumnist Use dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) it works ok.But,
NSManagedObjectContext * context = [[[XMPPManager defaultManager] rosterStorage] mainThreadManagedObjectContext]; context is nil.Have any solution?

@ObjColumnist
Copy link
Collaborator

I don't know how your XMPPManger works but I'm guessing rosterStorage is nil

@kartikthapar
Copy link

I faced the same issue when using a subclassed XMPPRoomCoreDataStorage API. I can confirm that Spencer's fix worked. @ObjColumnist, could you please shed some light as to why this was an issue?

@ObjColumnist
Copy link
Collaborator

Which bit in particular? this issue had a couple of tangents 😄

@kartikthapar
Copy link

@ObjColumnist I wasn't sure myself. But I found something weird.

I am using this framework for persistent room storage; more like WhatsApp. I basically join the room every time the user opens the app and download the required amount of history. There is a small (big?) issue with the above approach. The xmppRoomDidCreate delegate API is called twice for the same room. This doesn't happen when i create the room as follows:

FMXMPPRoom *room = [[FMXMPPRoom alloc] initWithRoomStorage:roomStorage jid:roomJID dispatchQueue:dispatch_get_main_queue()];

but fails for:

FMXMPPRoom *room = [[FMXMPPRoom alloc] initWithRoomStorage:roomStorage jid:roomJID dispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];

Thats one of the things I was talking about — if it could affect the program in different ways. I consider this to be a small issue as I have a small work around — basically check my core data if the room exists; add if it does not (similar to what I do in xmppRoomDidJoin for invites). I can add the same check to xmppRoomDidCreate but I am quite uneasy about this whole process as this small change in room creation could have other unknown side effects.

@ObjColumnist
Copy link
Collaborator

I'm guessing it's a race condition coupled with fact the XMPPRoom doesn't check its current state, so that delegate could be fired an infinite amount of times.

I haven't used MUC so I couldn't comment on if this is expected or a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants