how do I debug a wait_fences error - ios

wait_fences: failed to receive reply: 10004003
I continue to get this error. It happens when my app starts up. How would I debug this issue. Is there some way I can watch the wait_fences and see what is going on there. Is there some way to see what threads are blocking what ?
It feels like this error is nothing but a theading black hole with no tools or info getting into or coming out of the void.
Anyone with tips on debugging this error would be greatly appreciated.
New
I have now changed my threading, All threading calls go through this method set to do all their dispatches
NOTE: Also I wish you guys would not vote to close my question just because you have seen another question about this problem. There is no real information about this error. I need to know what causes this error and/or how to debug it. not the common "add the super calls to your viewDidAppear and the such. If those helped, I would not have asked this question.
+ (void) ensureDispatchOfBlock:(dispatch_block_t) block onQueue:(dispatch_queue_t) queue async:(BOOL) async{
if (dispatch_get_current_queue() == queue){
block();
}
else {
if (async){
dispatch_async(queue, block);
}
else {
dispatch_sync(queue, block);
}
}
}
+ (void) ensureDispatchOnMainThread:(dispatch_block_t) block async:(BOOL) async{
[self ensureDispatchOfBlock:block onQueue:dispatch_get_main_queue() async:async];
}
+ (BOOL) addBlock:(dispatch_block_t) block toQueue:(dispatch_queue_t) queue async:(BOOL) async {
if (!async && dispatch_get_current_queue() == queue){
return NO;
}
if (async){
dispatch_async(queue, block);
}
else {
dispatch_sync(queue, block);
}
return YES;
}

That error usually comes up as a result of trying to animate something that isn't visible on-screen. If it happens on launch, I'd guess that you're trying to start an animation in viewDidLoad.

I'd look for missing calls to super's view(Did/Will)Appear. If these are omitted you will see "wait fences", whatever that means.

Related

Function cannot run concurrently

I would like to make a function that only run once and cancel if is still running.
I tried it using a simple lock boolean on start/end, but sometimes it's "overlapping".
There's a better and secure way to do that?
#property (assign) BOOL lock;
- (void)myFuntion
{
if (self.lock) {
NSLog(#"(Canceled) Syncing is already running...");
return;
}
self.lock = YES;
// My Code
self.lock = NO;
}
The NSLock class should be able to help you here. I have not tried this example directly, but something like:
NSLock *myFunctionLock=[NSLock new]; // this should be a class data member/property/etc.
- (void)myFuntion
{
if (![myFunctionLock tryLock])
return; /* already running */
// My Synchronized Code
[myFunctionLock unlock];
}
We are all assuming that you are talking about concurrent programming, where you are running the same code on different threads. If that's not what you mean then you would need to explain what you DO mean, since code that runs on the same thread can only execute a function once at any particular moment.
Take a look at NSLock's tryLock function. The first caller to assert the lock gets back a TRUE, and can proceed to access the critical resource. Other callers get back FALSE and should not access the critical resource, but won't block.

Why cancelled AFHTTPRequestOperation sometimes hit the success block?

I'm integrating autocomplete on a search bar through Google Places API. And for the networking requests, I use AFNetworking.
I want to have only one request running at a time. So everytime I type a new letter, I do the following:
1 - Cancel the previous AFHTTPRequestOperation:
[self.currentGlobalSearchListRequest cancel];
NSLog(#"%# cancelled", self.currentGlobalSearchListRequest);
2 - Start a new AFHTTPRequestOperation:
self.currentGlobalSearchListRequest = [searchService getGlobalSearchListItemsForString:searchString inRegion:region delegate:self];
NSLog(#"%# started", self.currentGlobalSearchListRequest);
Here is the callback called when the request has finished running:
- (void)request:(PointSearchRequest *)request didLoadSearchListItems:(NSArray *)searchListItems {
NSAssert(request == self.currentGlobalSearchListRequest, #"!!!callback from a request that should be cancelled!!!");
[self.delegate searchListLoader:self didLoadGlobalSearchList:searchListItems];
}
Sometimes I hit the assertion, so I investigated a bit and discovered that most of the times
the failure block is called with an error code NSURLErrorCancelled which is the expected behavior but sometimes, the success block is called!
This stack trace tells me that things in my code occurred in the right order
2013-12-22 09:38:46.484 Point[63595:a0b] <PointSearchRequest: 0x18202b50> started
2013-12-22 09:38:46.486 Point[63595:a0b] <PointSearchRequest: 0x18202b50> cancelled
2013-12-22 09:38:46.487 Point[63595:a0b] <PointSearchRequest: 0x181a5dd0> started
2013-12-22 09:38:46.496 Point[63595:a0b] *** Assertion failure in -[SearchListLoader request:didLoadSearchListItems:], /Users/aurelienporte/Documents/Developpement/Perso/iOS/Point/Point/Classes/Models/SearchListLoader.m:82
(lldb) po request
<PointSearchRequest: 0x18202b50>
Plus, I looked at the property isCancelled on AFHTTPRequestOperation when success block is called but it gives me NO (!!!)
I know I could end up just testing instead of using NSAssert but would like to find the origin of the problem.
Have you ever encountered similar issues where cancel does not actually cancel the request? And then the success block is called instead of the failure block? Is this an issue to report to AFNetworking team? Thanks!
If it can help, the requests are freaking fast (Google autocomplete aPI is impressive...)
Looking into AFNetworkingCode, see AFURLConnectionOperation.m, line 461
- (void)cancel {
[self.lock lock];
if (![self isFinished] && ![self isCancelled]) {
[super cancel];
if ([self isExecuting]) {
[self performSelector:#selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
}
}
[self.lock unlock];
}
It seems that the only possibility for the race condition you are seeing is the case when the operation has already been finished ([self isFinished]). Note that the interval between your cancel and completion block is very small (10 ms). Maybe you could check isFinished before trying to cancel the request?
As we all know, a thread function will go no although you cancel the thread in the midway, when it start, it will complete the method. So as the request. That is, if the request is still in the NSOperationQueue, you can cancel it, but as long as you summit the operation,and the block is copy,it will call back.
If you don't want to accept the call back, you can just in the call back to tell whether the request is canceled.
Hope that it will help you.

Serializing asynchronous tasks in objective C

I wanted to be able to serialize 'genuinely' async methods, for example:
making a web request
showing a UIAlertView
This is typically a tricky business and most samples of serial queues show a 'sleep' in an NSBlockOperation's block. This doesn't work, because the operation is only complete when the callback happens.
I've had a go at implementing this by subclassing NSOperation, here's the most interesting bits of the implementation:
+ (MYOperation *)operationWithBlock:(CompleteBlock)block
{
MYOperation *operation = [[MYOperation alloc] init];
operation.block = block;
return operation;
}
- (void)start
{
[self willChangeValueForKey:#"isExecuting"];
self.executing = YES;
[self didChangeValueForKey:#"isExecuting"];
if (self.block) {
self.block(self);
}
}
- (void)finish
{
[self willChangeValueForKey:#"isExecuting"];
[self willChangeValueForKey:#"isFinished"];
self.executing = NO;
self.finished = YES;
[self didChangeValueForKey:#"isExecuting"];
[self didChangeValueForKey:#"isFinished"];
}
- (BOOL)isFinished
{
return self.finished;
}
- (BOOL) isExecuting
{
return self.executing;
}
This works well, here's a demonstration...
NSOperationQueue *q = [[NSOperationQueue alloc] init];
q.maxConcurrentOperationCount = 1;
dispatch_queue_t queue = dispatch_queue_create("1", NULL);
dispatch_queue_t queue2 = dispatch_queue_create("2", NULL);
MYOperation *op = [MYOperation operationWithBlock:^(MYOperation *o) {
NSLog(#"1...");
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(#"1");
[o finish]; // this signals we're done
});
}];
MYOperation *op2 = [MYOperation operationWithBlock:^(MYOperation *o) {
NSLog(#"2...");
dispatch_async(queue2, ^{
[NSThread sleepForTimeInterval:2];
NSLog(#"2");
[o finish]; // this signals we're done
});
}];
[q addOperations:#[op, op2] waitUntilFinished:YES];
[NSThread sleepForTimeInterval:5];
Note, I also used a sleep but made sure these were executing in background thread to simulate a network call. The log reads as follows
1...
1
2...
2
Which is as desired. What is wrong with this approach? Are there any caveats I should be aware of?
"Serializing" asynchronous tasks will be named actually "continuation" (see also this wiki article Continuation.
Suppose, your tasks can be defined as an asynchronous function/method with a completion handler whose parameter is the eventual result of the asynchronous task, e.g.:
typedef void(^completion_handler_t)(id result);
-(void) webRequestWithCompletion:(completion_handler_t)completionHandler;
-(void) showAlertViewWithResult:(id)result completion:(completion_handler_t)completionHandler;
Having blocks available, a "continuation" can be easily accomplished through invoking the next asynchronous task from within the previous task's completion block:
- (void) foo
{
[self webRequestWithCompletion:^(id result) {
[self showAlertViewWithResult:result completion:^(id userAnswer) {
NSLog(#"User answered with: %#", userAnswer);
}
}
}
Note that method foo gets "infected by "asynchrony" ;)
That is, here the eventual effect of the method foo, namely printing the user's answer to the console, is in fact again asynchronous.
However, "chaining" multiple asynchronous tasks, that is, "continuing" multiple asynchronous tasks, may become quickly unwieldy:
Implementing "continuation" with completion blocks will increment the indentation for each task's completion handler. Furthermore, implementing a means to let the user cancel the tasks at any state, and also implement code to handle the error conditions, the code gets quickly confusing, difficult to write and difficult to understand.
A better approach to implement "continuation", as well as cancellation and error handling, is using a concept of Futures or Promises. A Future or Promise represents the eventual result of the asynchronous task. Basically, this is just a different approach to "signal the eventual result" to the call site.
In Objective-C a "Promise" can be implemented as an ordinary class. There are third party libraries which implement a "Promise". The following code is using a particular implementation, RXPromise.
When utilizing such a Promise, you would define your tasks as follows:
-(Promise*) webRequestWithCompletion;
-(Promise*) showAlertViewWithResult:(id)result;
Note: there is no completion handler.
With a Promise, the "result" of the asynchronous task will be obtained via a "success" or an "error" handler which will be "registered" with a then property of the promise. Either the success or the error handler gets called by the task when it completes: when it finishes successfully, the success handler will be called passing its result to the parameter result of the success handler. Otherwise, when the task fails, it passes the reason to the error handler - usually an NSError object.
The basic usage of a Promise is as follows:
Promise* promise = [self asyncTasks];
// register handler blocks with "then":
Promise* handlerPromise = promise.then( <success handler block>, <error handler block> );
The success handler block has a parameter result of type id. The error handler block has a parameter of type NSError.
Note that the statement promise.then(...) returns itself a promise which represents the result of either handler, which get called when the "parent" promise has been resolved with either success or error. A handler's return value may be either an "immediate result" (some object) or an "eventual result" - represented as a Promise object.
A commented sample of the OP's problem is shown in the following code snippet (including sophisticated error handling):
- (void) foo
{
[self webRequestWithCompletion] // returns a "Promise" object which has a property "then"
// when the task finished, then:
.then(^id(id result) {
// on succeess:
// param "result" is the result of method "webRequestWithCompletion"
return [self showAlertViewWithResult:result]; // note: returns a promise
}, nil /*error handler not defined, fall through to the next defined error handler */ )
// when either of the previous handler finished, then:
.then(^id(id userAnswer) {
NSLog(#"User answered with: %#", userAnswer);
return nil; // handler's result not used, thus nil.
}, nil)
// when either of the previous handler finished, then:
.then(nil /*success handler not defined*/,
^id(NEError* error) {
// on error
// Error handler. Last error handler catches all errors.
// That is, either a web request error or perhaps the user cancelled (which results in rejecting the promise with a "User Cancelled" error)
return nil; // result of this error handler not used anywhere.
});
}
The code certainly requires more explanation. For a detailed and a more comprehensive description, and how one can accomplish cancellation at any point in time, you may take a look at the RXPromise library - an Objective-C class which implements a "Promise". Disclosure: I'm the author of RXPromise library.
At a first glance this would work, some parts are missing to have a "proper" NSOperation subclass though.
You do not cope with the 'cancelled' state, you should check isCancelled in start, and not start if this returns YES ("responding to the cancel command")
And the isConcurrent method needs to be overridden too, but maybe you omitted that for brevity.
When subclassing NSOperation I would strongly suggest only overriding main unless you really know what you are doing as it is really easy to mess up thread safety. While the documentation says that the operation will not be concurrent the act of running them through an NSOperationQueue automatically makes them concurrent by running them on a separate thread. The non-concurrency note only applies if you call the start method of the NSOperation yourself. You can verify this by noting the thread ID that each NSLog line contains. For example:
2013-09-17 22:49:07.779 AppNameGoesHere[58156:ThreadIDGoesHere] Your log message goes here.
The benefit of overriding main means that you don't have to deal with thread safety when changing the state of the operation NSOperation handles all of that for you. The main thing that is serializing your code is the line that sets maxConcurrentOperationCount to 1. This means each operation in the queue will wait for the next to run (all of them will run on a random thread as determined by the NSOperationQueue). The act of calling dispatch_async inside each operation also triggers yet another thread.
If you are dead set on using subclassing NSOperation then only override main, otherwise I would suggest using NSBlockOperation which seems like what you are somewhat replicating here. Really though I would avoid NSOperation altogether, the API is starting to show its age and is very easy to get wrong. As an alternative I would suggest something like RXPromise or my own attempt at solving this problem, FranticApparatus.

How can I wait for a NSURLConnection delegate to finish before executing the next statement?

This has been a hard one to search.
I found a similar question, iOS 5 Wait for delegate to finish before populating a table?, but the accepted answer was 'Refresh the table view,' and that does not help me. The other results I found tended to be in c#.
I have an app that streams from iPhone to Wowza servers. When the user hits record, I generate a unique device id, then send it to a PHP script on the server that returns a JSON document with configuration settings (which includes the rtmp dump link).
The problem is, the delegate methods are asynchronous, but I need to get the config settings before the next lines of code in my - (IBAction)recordButtonPressed method, since that code is what sets the profile settings, and then records based on those settings.
I've realized I could make the NSURLConnection in -recordButtonPressed like I am currently, and then continue the setup code inside the delegate method connectionDidFinishLoading (or just encapsulate the setup and method call it from there) but that's sacrificing coherent design for functionality and that sucks.
Is there not some simple waitUntilDelegateIsFinished:(BOOL)nonAsyncFlag flag I can send to the delegator so I can have sequential operations that pull data from the web?
I've realized I could make the NSURLConnection in -recordButtonPressed like I am currently, and then continue the setup code inside the delegate method connectionDidFinishLoading (or just encapsulate the setup and method call it from there) but that's sacrificing coherent design for functionality and that sucks.
You have analyzed and understood the situation and you have described its possible solutions perfectly. I just don't agree with your conclusions. This kind of thing happens all the time:
- (void) doPart1 {
// do something here that will eventually cause part2 to be called
}
- (void) doPart2 {
}
You can play various games with invocations to make this more elegant and universal, but my advice would be, don't fight the framework, as what you're describing is exactly the nature of being asynchronous. (And do not use a synchronous request on the main thread, since that blocks the main thread, which is a no-no.)
Indeed, in an event-driven framework, the very notion "wait until" is anathema.
Why not to use synchronous request?
Wrap your asynchronous NSURLConnection request in a helper method which has a completion block as a parameter:
-(void) asyncDoSomething:(void(^)(id result)completionHandler ;
This method should be implemented in the NSURLConnectionDelegate. For details see the example implementation and comments below.
Elsewhere, in your action method:
Set the completion handler. The block will dispatch further on the main thread, and then perform anything appropriate to update the table data, unless the result was an error, in which case you should display an alert.
- (IBAction) recordButtonPressed
{
[someController asyncConnectionRequst:^(id result){
if (![result isKindOfClass:[NSError class]]) {
dispatch_async(dispatch_get_main_queue(), ^{
// We are on the main thread!
someController.tableData = result;
});
}
}];
}
The Implementation of the method asyncConnectionRequst: could work as follows: take the block and hold it in an ivar. When it is appropriate call it with the correct parameter. However, having blocks as ivars or properties will increase the risk to inadvertently introduce circular references.
But, there is a better way: a wrapper block will be immediately dispatched to a suspended serial dispatch queue - which is hold as an ivar. Since the queue is suspended, they will not execute any blocks. Only until after the queue will be resumed, the block executes. You resume the queue in your connectionDidFinish: and connectionDidFailWithError: (see below):
In your NSURLConnectionDelegate:
-(void) asyncConnectionRequst:(void(^)(id result)completionHandler
{
// Setup and start the connection:
self.connection = ...
if (!self.connection) {
NSError* error = [[NSError alloc] initWithDomain:#"Me"
code:-1234
userInfo:#{NSLocalizedDescriptionKey: #"Could not create NSURLConnection"}];
completionHandler(error);
});
return;
}
dispatch_suspend(self.handlerQueue); // a serial dispatch queue, now suspended
dispatch_async(self.handlerQueue, ^{
completionHandler(self.result);
});
[self.connection start];
}
Then in the NSURLConnectionDelegate, dispatch a the handler and resume the
handler queue:
- (void) connectionDidFinishLoading:(NSURLConnection*)connection {
self.result = self.responseData;
dispatch_resume(self.handlerQueue);
dispatch_release(_handlerQueue), _handlerQueue = NULL;
}
Likewise when an error occurred:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
self.result = error;
dispatch_resume(self.handlerQueue);
dispatch_release(_handlerQueue), _handlerQueue = NULL;
}
There are even better ways, which however involve a few more basic helper classes which deal with asynchronous architectures which at the end of the day make your async code look like it were synchronous:
-(void) doFourTasksInAChainWith:(id)input
{
// This runs completely asynchronous!
self.promise = [self asyncWith:input]
.then(^(id result1){return [self auth:result1]);}, nil)
.then(^(id result2){return [self fetch:result2];}, nil)
.then(^(id result3){return [self parse:result3];}, nil)
.then(^(id result){ self.tableView.data = result; return nil;}, ^id(NSError* error){ ... })
// later eventually, self.promise.get should contain the final result
}

Ensuring the codes in different sections run in the background queue in iOS

I am new to multithreading in iOS. I need to do three things: get information from the api, parse the information and save to my database. I have these three things in a different files(getAPI,parseAPI and savetoDB). getAPI will call parseAPI and it will in return call savetoDB. I want all three of them to work in background thread.
My question is when I call getAPI, will parseAPI and savetoDB run in the background thread as well? How do I ensure that all three of them run in the background? How do I return the call back to main thread after savetoDB?
Example:
dispatch_queue_t backgroundQueue;
backgroundQueue = dispatch_queue_create("lakesh", NULL);
- (void)startprocess {
dispatch_async(backgroundQueue, ^(void) {
[self getAPI];
});
}
Need some guidance.. Thanks...
If you issue a function on a background thread, all execution will continue on that thread until it finishes or you call back another function on the main thread. I had worries like you in the beginning, so I made myself the following macros:
/// Stick this in code you want to assert if run on the main UI thread.
#define DONT_BLOCK_UI() \
NSAssert(![NSThread isMainThread], #"Don't block the UI thread please!")
/// Stick this in code you want to assert if run on a background thread.
#define BLOCK_UI() \
NSAssert([NSThread isMainThread], #"You aren't running in the UI thread!")
As you can see by the comments, I tend to use these macros at the beginning of methods I want to make sure I'm not using by error in the wrong thread. I've put these macros and more random stuff at https://github.com/gradha/ELHASO-iOS-snippets which you may find useful.
With regards to your question on returning to the main thread, since you are using GCD the best would be to call dispatch_get_main_queue() at the end of your savetoDB with the code you want to run there. If savetoDB is a library function, its entry point should allow passing in the success block you want to run on the main thread when everything finished. This is the pattern used by libraries like https://github.com/AFNetworking/AFNetworking. Note how their examples provide an API where stuff runs in the background and then your code gets called back (usually in the main thread).
Yes, parseAPI and savetoDB will run in the new queue you have created. If you need to modify the UI when the operations are finished, that code must run in the main thread. To do that, get a reference to the main queue and send it some code. For example:
- (void)startprocess {
dispatch_async(backgroundQueue, ^(void) {
[self getAPI];
dispatch_async(dispatch_get_main_queue(), ^{
// Refresh the UI with the new information
});
});
}
Don't forget to dispatch_release your new queue when you're done with it.
Another pattern, used by Cocoa itself in many parts of the framework, is to add callback block to the signatures of your API functions that is invoked when the background operation has ended. This Stack Overflow thread explains how to do that.
Yes of course if getAPI calls parseAPI, the code of parseAPI will execute on the same thread than the one getAPI was executed, so in your example on a background queue.
To return the callback to the main thread at the end, use the same techniques as Apple uses with their completionBlock you can see on multiple Apple APIs : simply pass a block (e.g. dispatch_block_t or void(^)(NSError*) or whatever fits your needs) as a parameter to your getAPI: method which will pass it to parseAPI: which will in turn pass it to savetoDB: and at the end savetoDB: can simply use dipatch_async(dispatch_get_main_queue, completionBlock); to call this block of code (passed from method to method) on the main thread.
Note: for your getAPI you can use Apple's sendAsynchronousRequest:queue:completionHandler: method, that will automatically execute the request in the background then call the completion block on the indicated NSOperationQueue (NSOperationQueue uses GCD's dispatch_queue internally). See documentation on NSOperationQueue, GCD and the Concurrency Programming Guide and all the great detailed guide in Apple doc for more info.
-(void)getAPI:( void(^)(NSError*) )completionBlock
{
NSURLRequest* req = ...
NSOperationQueue* queue = [[NSOperationQueue alloc] init]; // the completionHandler will execute on this background queue once the network request is done
[NSURLConnection sendAsynchronousRequest:req queue:queue completionHandler:^(NSURLResponse* resp, NSData* data, NSError* error)
{
if (error) {
// Error occurred, call completionBlock with error on main thread
dispatch_async(dispatch_get_main_queue(), ^{ completionBlock(error); });
} else {
[... parseAPI:data completion:completionBlock];
}
}];
}
-(void)parseAPI:(NSData*)dataToParse completion:( void(^)(NSError*) )completionBlock
{
... parse datatToParse ...
if (parsingError) {
dispatch_async(dispatch_get_main_queue(), ^{ completionBlock(error); });
} else {
[... savetoDB:dataToSave completion:completionBlock];
}
}
-(void)savetoDB:(id)dataToSave completion:( void(^)(NSError*) )completionBlock
{
... save to your DB ...
// Then call the completionBlock on main queue / main thread
dispatch_async(dispatch_get_main_queue(), ^{ completionBlock(dbError); }); // dbError may be nil if no error occurred of course, that will tell you everything worked fine
}
-(void)test
{
[... getAPI:^(NSError* err)
{
// this code will be called on the main queue (main thread)
// err will be nil if everythg went OK and vontain the error otherwise
}];
}

Resources