Mediapipe: How to properly dealloc MPPGraph - mediapipe

It is unclear to me how to properly stop and deallocate the MPPGraph. I created a framework very similar to this. Every time a dealloc is called in some way this exception is thrown. Thread 1: Exception: "waitUntilDoneWithError: should not be called on the main thread".
I don't know how to not call it in the main thread and was hoping someone had some insight on this.
Here you can find the swift code that is calling the mediapipe framework. This example has been created with the framework that can be found here.

For anyone experiencing same issue. This has been addressed here and a solution has been proposed.
Edit:
This last bit might be wrong but I used dealloc in this way:
- (void)dealloc {
self.mediapipeGraph.delegate = nil;
[self.mediapipeGraph cancel];
// Ignore errors since we're cleaning up.
[self.mediapipeGraph closeAllInputStreamsWithError:nil];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.mediapipeGraph waitUntilDoneWithError:nil];
});
}

Related

Why am I getting NSFastEnumerationMutationHandler in code that doesn't modify source array/set?

In my crash logs for my latest app version, I got an NSFastEnumerationMutationHandler followed by a crash referencing HKAnchoredObjectQuery initWithType for my code, but I am not intentionally mutating the NSMutableSet sources over which I am fast enumerating.
Here's my code:
for(HKSource* source in sources){
NSPredicate *predicate = [HKQuery predicateForObjectsFromSources:[NSSet setWithObject:source]];
HKAnchoredObjectQuery *newQuery = [[HKAnchoredObjectQuery alloc] initWithType:quantityType predicate:predicate anchor:anchor limit:HKObjectQueryNoLimit completionHandler:^(HKAnchoredObjectQuery *query, NSArray *results, NSUInteger newAnchor, NSError *error) {
completion(results);
}];
[healthStore executeQuery:newQuery];
}
Any suggestions as to why I am triggering NSFastEnumerationMutationHandler? I am not explicitly touching sources nor have I made a copy of it...is there a way HealthKit could be modifying the source? Even if it were, I would think that modifying source shouldn't trigger this as I am not directly touching sources. Any trouble-shooting advice or error-spotting would be much appreciated.
Here's the exact text from the crash log:
Latest Exception Backtrace:
1. libobjc.A.dylib objc_exception_throw
2. CoreFoundation _NSFastEumerationMutationHandler
3. App name 0x1000d8000
4. App name 0x1000d8000
5. App name 0x1000d8000
6. HealthKit _79-[HKAnchoredObjectQuery initWithType:predicate:anchor:limit:completionHandler:]_block_invoke <---this must be referring to my code above, as it's the only call to initWithType inside a fast enumeration
7. HealthKit _81-[HKAnchoredObjectQuery deliverSampleObjects:deletedObjects:withAnchor:forQuery:]_block_invoke_2 <-- this is an internal HealthKit call. deliverSampleObjects is not a publicly listed method of the interface.
I have not had a crash in the sim or on my phone, so this is the only info I have to go on.
Some code that gets called by the block named completion() in your code snippet is iterating over another collection and is doing so while that array is being modified. Keep in mind that the completionHandler of HKAnchoredObjectQuery runs on a background thread, so your code may be performing unsafe concurrent operations on objects when completionHandler gets called.
It looks like this happens in a block somewhere in a method named
[HKAnchoredObjectQuery initWithType:predicate:anchor:limit:completionHandler:]
So my guess is that the block in question is the completion handler, and the completion handler gets called asynchronously - while someone else is iterating through the same array and maybe modifying it.
Unfortunately this error doesn't show who is causing the trouble, only who is finding the trouble. I'd set a breakpoint on your own callback, check if it is called from a fast enumeration, and try to figure out who else might be modifying the data. Good luck.

Parse login hang since Facebook 4.0.x with [PFFacebookUtils initializeFacebookWithApplicationLaunchOptions:launchOptions] (semaphore_wait_slow trap)

Since updating Facebook to v4.0.x and the latest Parse libraries, my app is hanging, seemingly when trying to log in the user.
My stack trace looks like this:
I had a very similar problem previously, answered here: Parse crash when calling [PFFacebookUtils initializeFacebook] - semaphore_wait_trap
However that solution no longer works, since it seems [PFUser currentUser] has been replaced with [PFUser(Private) _getCurrentUserWithOptions:] and [BFTask(Private) waitForResult:withMainThreadWarning:] where it gets stuck.
In my app, I've subclassed PFUser to a class called MPLUser, and overridden the user method. Not sure if this might be something to do with the issue?
+ (MPLUser *)user
{
return (MPLUser *)[PFUser user];
}
Once this starts occurring, it becomes impossible to launch the app. However, I usually manage to launch the app a few times before the lock starts happening. It usually happens after a crash...
I'm using pod 'ParseFacebookUtilsV4' and have updates all libraries to latest versions.
UPDATE:
Here's more stack trace from another thread, that is seemingly trying to log on:
I initialise Parse and Facebook in the following order. If I reverse the calls, it crashes:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self initDefaults];
[self initialiseApplicationSpecifics];
[self setupParseWithOptions:launchOptions];
[self enableCrashReporting];
[self setupIAPs];
//etc...
}
- (void)initialiseApplicationSpecifics
{
[Flurry setCrashReportingEnabled:YES];
[self registerParseSubclasses];
[ParseCrashReporting enable];
[Parse enableLocalDatastore];
#ifdef MPL
[Parse setApplicationId:#"xxxyyy"
clientKey:#"xxxyyy"];
[Flurry startSession:#"xxxyyy"];
#elif MGM
[Parse setApplicationId:#"yyyxxx"
clientKey:#"yyyxxx"];
[Flurry startSession:#"yyyxxx"];
#endif
}
- (void)setupParseWithOptions:(NSDictionary *)launchOptions
{
[PFFacebookUtils initializeFacebookWithApplicationLaunchOptions:launchOptions];
[PFTwitterUtils initializeWithConsumerKey:#"aaaabbbb"
consumerSecret:#"bbbbaaaa"];
[PFAnalytics trackAppOpenedWithLaunchOptions:launchOptions];
}
Seems to be fixed with parse 1.7.2
According to v1.7.2 — April 27, 2015
New: Local Data Sharing for Extensions and WatchKit.
Improved nullability annotations for ParseFacebookUtils.
Fixed: logOutInBackground with block callback not called on main thread.
Fixed: Potential compilation error with using imports for PFSubclassing.h.
Fixed: Not persistent currentUser if saving automatic user via saveEventually.
Fixed: Rare deadlock scenario with using ParseFacebookUtils and currentUser.
Fixed: Rare issue with pinning multiple objects in a row to the same pin.
Fixed: Rare scenario when user could be not linked with Facebook.
Improved performance and reliability of Local Datastore.
Performance improvements.
Other small bug fixes.
I'm having the same problem with Parse 1.7.1 & FBSDK 4.0.1 and I reported the bug to Parse but with no luck so far. It has something to do with the local datastore.
https://developers.facebook.com/bugs/779176035499837
Please provide further info there.
I checked with my team working on the iOS SDK and was informed the latest SDK should resolve this. Can you try updating?

no Objective-C description available - Why?

I really have no idea why on this particular project my debugger is extremely 'disabled'.
For example I'll want to get info on an object:
(lldb) po [_model dictionaryValue]
[no Objective-C description available]
I'm wondering why this is. It's making debugging extremely difficult and it's only on this current project. I'm guessing I've done something to the settings at some point. It's on almost any po someObject I try to inspect. The variables in scope can be seen in the pane to the left of the debug console however.
I'm on Xcode 5, I have Cocoapods in my project, and it's a Unit Testing Target.
Any insights or any way to fix this?
Update:
For clarity, part of how the test case is implemented:
#interface WWCGateModelTests : XCTestCase
{
WWCGate *_model;
}
#end
#implementation WWCGateModelTests
- (void)setUp
{
[super setUp];
// Put setup code here; it will be run once, before each test case.
_model = [WWCGate loadGateModelWithIdentifier: kGateName]; // defined, not nil
}
- (void)tearDown
{
[super tearDown];
NSError *error = nil;
[_model saveModelOrError:&error];
// Breakpoint here. po _model does not print the model.
// This has been possible with other projects... po error will print
// nil to the console. How is an ivar not in scope?
}
This is likely happening because Unit Testing Targets typically are set up to run with "Release" configurations. "Release" configurations are ones where the debugging symbols have been stripped or optimized away.
I suspect you won't have this problem if you make certain you're running with a non-optimized, symbols-in-place Debug version of your app. You can change that in Xcode's scheme editor (e.g. when doing "Test" or "Profile", use the "Debug" configuration).
Are you sure you aren't using it on primitive types? Use p intVariable on those.
Every object will respond to description by at least printing class and memory address.
I've tracked down the issue (but haven't fixed it fully yet). It has to do with the Mantle Framework. In its description method it wants to spit out the contents of an NSDictionary that it generates at that point. There's something wrong with the way I set up my model I believe so creating this dictionary (based probably on how I configured some property) is basically failing.
I overrode the description method to return a standard description:
- (NSString*)description
{
return [NSString stringWithFormat:#"<%#: %p>", self.class, self];
}
and everything is fine and good again on planet Earth. ;-)
Thanks to those who were particularly patient. A more detailed discussion about this issue can be found at UPDATE 3 of the following post: http://horseshoe7.wordpress.com/2013/05/26/hands-on-with-the-mantle-model-framework/

Weird EXC_BAD_ACCESS in a trivial PDFKit program

I have written this trivial action method associated to a textfield.
Every time I enter text into a textfield a search in a PDF is performed and PDFView automatically scroll to selection:
- (IBAction) search:(id)id
{
NSString *query = [self.searchView stringValue]; // get from textfield
selection = [document findString: query fromSelection:NULL withOptions:NSCaseInsensitiveSearch];
if (selection != nil)
{
[self.pdfView setCurrentSelection:selection];
[self.pdfView scrollSelectionToVisible:self.searchView];
}
}
Problem is that after 3 or 4 searches I get EXC_BAD_ACCESS on row (i).
If I debug I see that query contains an NSCFString and not an NSString.
I think it is a memory management problem..but where?
I replicated the same issue inside a trivial testcase:
#interface PDFRef_protoTests : SenTestCase {
#private
PDFDocument *document;
}
........
- (void)setUp
{
[super setUp];
document = [[PDFDocument alloc] initWithURL: #"a local url ..."];
}
- (void)test_exc_bad_access_in_pdfdocument
{
for (int i =0 ;i<100; i++)
{
NSString *temp;
if (i % 2 == 0) temp = #"home";
else if (i % 3 ==0) temp = #"cocoa";
else temp=#"apple";
PDFSelection *selection = [document findString: temp
fromSelection:nil
withOptions:NSCaseInsensitiveSearch];
NSLog(#"Find=%#, iteration=%d", selection, i);
}
}
Update:
1) It seems that it happens also if I use asynchronous search (method beginFindString: withOptions) every time I perform second search.
2) I found a similar problem to mine in MacRuby Issue Tracking: http://www.macruby.org/trac/ticket/1029
3) It seems that if I disable temporarily garbage collection it works but memory goes up.
I wrote something like:
[[NSGarbageCollector defaultCollector] disable];
[[NSGarbageCollector defaultCollector] enable];
surrounding search code
Another Update
Very weird thing is that sometimes all works. Than I clean and Rebuild and problem arises again. From a certain point of view is is not 100% reproducible. I suspect a bug in PDFKit or some compiler setting I have to do
Update Again
Dears it seems very crazy. I'd concentrate on testcase which is very trivial and which replicates easily the problem. What's wrong with it? This testcase works only if I disable (by code or by project setting) GC
Another Update
Boys it seems a bug but I downloaded an example called PDFLinker from Apple website (http://developer.apple.com/library/mac/#samplecode/PDFKitLinker2/Introduction/Intro.html#//apple_ref/doc/uid/DTS10003594). This example implements a PDFViewer. Code of my app and this example are quite similars. For the same search action on same PDF, my memory rises at 300/400 MB while PDFLinker rises at 190MB. Clearly there is something wrong in my code. But I am comparing it bit by bit and I don't think I am inserting memory leaks (and Instrument doesn't give me any evidence). Maybe is there some project-wide setting ?
Update Yet
Changing from 64 bit to 32 bit memory consumption lowered. Surely there is a problem with 64bit and PDFKit. BTW still EXC_BAD_ACCESS on second search
SOLUTION
Crucial point is that PDFKit with Garbage collection is bugged.
If I disable GC all works correctly.
I had another issue that had complicated my analysis: I disabled GC on Project Setting but GC remained enabled on Target Settings. So Apple's example PDFLinked2 worked while mine not.
I agree you have found a bug in PDFKit.
I got various forms of errors (segmentation fault, selector not understood, etc) running your test case. Wrapping the code in #try/#catch doesn't prevent all errors associated with this method.
I also got errors printing the log message.
To work around the bug(s), I suggest you disable GC during your invocation of -findString:fromSelection:, as you've already discovered.
Also, be sure to make copies of the values of interest from selection before re-enabling GC. Don't just copy selection either.
If you conduct searches from multiple places in your code I also suggest you extract a separate method to perform the search. Then you can invoke that one to conduct the searches for you without duplicating the GC disable/enable nesting.
This sort of thing is usually evidence that you're hanging onto a pointer to an object that has been destroyed. Turn on zombie objects (with NSZombieEnabled) to see exactly where and when you're accessing a bad object.
Judging from your screen shot it doesn't seem like you have NSZombie turned on. Probably the reason why it doesn't help you. Here's how you turn it on:
How to enable NSZombie in Xcode?
The screenshot you provided was otherwise very useful, but you really need NSZombie to figure out this kind of errors. Well, unless it's obvious, which it isn't from the code you posted.
EDIT: I read the comment that you're using garbage collection. I'm an iOS developer, so I have very limited experience with garbage collection in Objective-C, but as far as I understand NSZombie doesn't work in a garbage collected environment.
I'm not sure it should be possible to get EXC_BAD_ACCESS in a garbage collected environment, unless you create your own pointer and try to call methods on it without having created an object and I don't see why you would do that.
I've heard that some frameworks doesn't work well with garbage collection, but I wouldn't think PDFKit was among them. Anyway, the solution might be to not use garbage collection. Perhaps you should file a bug report with Apple.
keep PDFSelection *selection as a member variable and pass it in fromSelection: instead of nil.
It is possible that PDFDocument keeps the returned PDFSelection instance to improve the performance.
Did you try retaining the searchview stringvalue object before using it?
As you say it happens when you type fast and it happens for async calls, it is possible that the object stringValue is pointing to is being released between the time your query object is pointing to it, and the time you use it int the search.
You could try something like this to see if the problem persists:
- (IBAction) search:(id)id
{
NSString *query = [[self.searchView stringValue] retain]; // get from textfield
selection = [document findString: query fromSelection:NULL withOptions:NSCaseInsensitiveSearch];
if (selection != nil)
{
[self.pdfView setCurrentSelection:selection];
[self.pdfView scrollSelectionToVisible:self.searchView];
}
[query release];
}
Of course there is also the possibility that document is relased. How do you declare it? is it a property with retain? Can it be released by the time you are searching?
EDIT:
I see that you posted the code with the second parameter as NULL, but in your screenshot, this value is nil.
The documentation says you should use NULL when you want to start the search from the beginning.
http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/QuartzFramework/Classes/PDFDocument_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40003873-RH2-DontLinkElementID_1
And as the compiler interprets nil and NULL differently, this could be leading to some weird behavior internally.

EXC BAD ACCESS from CoreGraphics API in NSOperation

I'm trying to do some CoreGraphics/CoreImage manipulation inside an NSOperation, using MacRuby. I have a few API calls that read a source file into CG and set up a CGImageDestination.
If I put the following code into an NSOperation.init, everything works great:
#dest = CGImageDestinationCreateWithURL(#photo.output_url, "public.jpeg" , 1, nil);
#context = CIContext.alloc.init
#cgOriginalImgSrc = CGImageSourceCreateWithURL(#photo.url, nil)
#cgOriginal = CGImageSourceCreateImageAtIndex(#cgOriginalImgSrc, 0, nil)
But if I put the same code into the main function for the NSOperation, I get sporadic EXC_BAD_ACCESS errors. And only when passing the NSOperation to an NSOperationQueue; if I invoke main myself, it works just fine.
At the end of the main I am running:
CFRelease(#dest)
CFRelease(#cgOriginalImgSrc)
CGImageRelease(#cgOriginal)
Even stranger is that it works in init, even if init isn't invoked from the main thread (so not a main thread/background thread issue, I'm guessing)
Any thoughts?
Looks like one of your threads is referring to an object that doesn't exist in memory anymore. Try removing
CFRelease(#dest)
CFRelease(#cgOriginalImgSrc)
CGImageRelease(#cgOriginal)
And see how it goes. Also you can try verifying your objects in each queue to see if they are still available. Finally, you could use macrubyd, the debugger for MacRuby to see what's going on, or even use GDB and paste the backtrace so we can see what the problem is.
Thanks,
Matt