Why am I getting deadlock with dispatch_once? - ios

Why am I deadlocking?
- (void)foo
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self foo];
});
// whatever...
}
I expect foo to be executed twice on first call.

Neither of the existing answers are quite accurate (one is dead wrong, the other is a bit misleading and misses some critical details). First, let's go right to the source:
void
dispatch_once_f(dispatch_once_t *val, void *ctxt, dispatch_function_t func)
{
struct _dispatch_once_waiter_s * volatile *vval =
(struct _dispatch_once_waiter_s**)val;
struct _dispatch_once_waiter_s dow = { NULL, 0 };
struct _dispatch_once_waiter_s *tail, *tmp;
_dispatch_thread_semaphore_t sema;
if (dispatch_atomic_cmpxchg(vval, NULL, &dow)) {
dispatch_atomic_acquire_barrier();
_dispatch_client_callout(ctxt, func);
dispatch_atomic_maximally_synchronizing_barrier();
//dispatch_atomic_release_barrier(); // assumed contained in above
tmp = dispatch_atomic_xchg(vval, DISPATCH_ONCE_DONE);
tail = &dow;
while (tail != tmp) {
while (!tmp->dow_next) {
_dispatch_hardware_pause();
}
sema = tmp->dow_sema;
tmp = (struct _dispatch_once_waiter_s*)tmp->dow_next;
_dispatch_thread_semaphore_signal(sema);
}
} else {
dow.dow_sema = _dispatch_get_thread_semaphore();
for (;;) {
tmp = *vval;
if (tmp == DISPATCH_ONCE_DONE) {
break;
}
dispatch_atomic_store_barrier();
if (dispatch_atomic_cmpxchg(vval, tmp, &dow)) {
dow.dow_next = tmp;
_dispatch_thread_semaphore_wait(dow.dow_sema);
}
}
_dispatch_put_thread_semaphore(dow.dow_sema);
}
}
So what really happens is, contrary to the other answers, the onceToken is changed from its initial state of NULL to point to an address on the stack of the first caller &dow (call this caller 1). This happens before the block is called. If more callers arrive before the block is completed, they get added to a linked list of waiters, the head of which is contained in onceToken until the block completes (call them callers 2..N). After being added to this list, callers 2..N wait on a semaphore for caller 1 to complete execution of the block, at which point caller 1 will walk the linked list signaling the semaphore once for each caller 2..N. At the beginning of that walk, onceToken is changed again to be DISPATCH_ONCE_DONE (which is conveniently defined to be a value that could never be a valid pointer, and therefore could never be the head of a linked list of blocked callers.) Changing it to DISPATCH_ONCE_DONE is what makes it cheap for subsequent callers (for the rest of the lifetime of the process) to check the completed state.
So in your case, what's happening is this:
The first time you call -foo, onceToken is nil (which is guaranteed by virtue of statics being guaranteed to be initialized to 0), and gets atomically changed to become the head of the linked list of waiters.
When you call -foo recursively from inside the block, your thread is considered to be "a second caller" and a waiter structure, which exists in this new, lower stack frame, is added to the list and then you go to wait on the semaphore.
The problem here is that this semaphore will never be signaled because in order for it to be signaled, your block would have to finish executing (in the higher stack frame), which now can't happen due to a deadlock.
So, in short, yes, you're deadlocked, and the practical takeaway here is, "don't try to call recursively into a dispatch_once block." But the problem is most definitely NOT "infinite recursion", and the flag is most definitely not only changed after the block completes execution -- changing it before the block executes is exactly how it knows to make callers 2..N wait for caller 1 to finish.

You could alter code a little, so that the calls are outside the block and there's no deadlock, something like this:
- (void)foo
{
static dispatch_once_t onceToken;
BOOL shouldRunTwice = NO;
dispatch_once(&onceToken, ^{
shouldRunTwice = YES;
});
if (shouldRunTwice) {
[self foo];
}
// whatever...
}

Related

Whether performBlockAndWait calling twice on single thread cause deadlock?

I have found something like this in performBlockAndWait documentation:
This method may safely be called reentrantly.
My question is whether it means that it never cause deadlock when I e.g. will invoke it like that on single context?:
NSManageObjectContext *context = ...
[context performBlockAndWait:^{
// ... some stuff
[context performBlockAndWait:^{
}];
}];
You can try it yourself with a small code snippet ;)
But true, it won't deadlock.
I suspect, the internal implementation uses a queue specific token in order to identify the current queue on which the code executes (see dispatch_queue_set_specific and dispatch_queue_get_specific).
If it determines that the current executing code executes on its own private queue or on a children-queue, it simply bypasses submitting the block synchronously - which would cause a dead-lock, and instead executing it directly.
A possible implementation my look as below:
func executeSyncSafe(f: () -> ()) {
if isSynchronized() {
f()
} else {
dispatch_sync(syncQueue, f)
}
}
func isSynchronized() -> Bool {
let context = UnsafeMutablePointer<Void>(Unmanaged<dispatch_queue_t>.passUnretained(syncQueue).toOpaque())
return dispatch_get_specific(&queueIDKey) == context
}
And the queue might be created like this:
private var queueIDKey = 0 // global
init() {
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
QOS_CLASS_USER_INTERACTIVE, 0))
let context = UnsafeMutablePointer<Void>(Unmanaged<dispatch_queue_t>.passUnretained(syncQueue).toOpaque())
dispatch_queue_set_specific(syncQueue, &queueIDKey, context, nil)
}
dispatch_queue_set_specific associates a token (here context - which is simply the pointer value of the queue) with a certain key for that queue. And later, you can try to retrieve that token for any queue specifying the key and check whether the current queue is the same queue or a children-queue. If this is true, bypass dispatching to the queue and instead call the function f directly.

Can a function return a value from an asynchronous block

Suppose this code without a block
int calculateValue (int a, int b) {
return doSomeStuff(a,b);
}
now suppose the function depends on something that is asynchronous. So I declare the asynchronous part as a block like this
int calculateValue (int a, int b) {
int (^myBlock)(int a, int b) = ^int(int a, int b) {
// do some complex asynchronous stuff
return result;
};
// can I do this?
return myBlock;
}
Is there any need to put the calculation inside the block into a dispatch_sync on main thread or something?
No you can't do that. The point of starting an async function is so that the caller can continue on with other work (perhaps launch other async functions?).
Assuming you are using dispatch_async() - from the docs:
The dispatch_async() function returns immediately, without waiting for the block to be invoked:
If you want to be able to work with result of the block from the caller you can pass in a reference to the caller as an argument to your block. Then when your async task is complete, call one of the caller's methods to pass your "return value".

stack and heap condition on recursive function or block?

Imagine a situation like this:
- (void)doSomethingWithView:(UIView)view {
for (UIView *oneView in view.subviews) {
[self doSomethingWithView:oneView];
}
}
or a block like
void (^doSomething)(NSArray *numbers);
doSomething = ^void(NSArray *numbers){
// ... bla bla
if (condition) {
doSomething(numbers);
}
};
What happens in terms of stack and heap? My feeling is that the blocks/functions may generate a lot of stuff on the stack and heap that will never released up to a point the the app will crash without memory.
Do I run this risk?
All depend from your code and quantity of recursion.
But in any case, you can do something like this:
void (^doSomething)(NSArray *numbers);
doSomething = ^void(NSArray *numbers){
// ... bla bla
if (condition) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ull), ^{
doSomething(numbers);
});
}
};
in this case you launch again the block but due the fact that you are using dispatch_async, the outer block return and the new block continue separately in the concurrent queue.

Need assistance regarding understanding typedefs and blocks

typedef void (^RequestProductsCompletionHandler)(BOOL success, NSArray * products);
I am having difficulty understanding what this line of code is doing in .h file.
Please explain in detail
typedef.
void (I know what void do, but whats the purpose here?).
(^RequestProductsCompletionHandler)(BOOL success, NSArray * products);
How to call it?
This is definition of objective-c block type with name RequestProductsCompletionHandler that takes 2 parameters (BOOL and NSArray) and does not have return value. You can call it the same way you would call c function, e.g.:
RequestProductsCompletionHandler handler = ^(BOOL success, NSArray * products){
if (success){
// Process results
}
else{
// Handle error
}
}
...
handler(YES, array);
Vladimir described it well. It defines a variable type which will represent a block that will pass two parameters, a boolean success and an array of products, but the block itself returns void. While you don't need to use the typedef, it makes the method declaration a tad more elegant (and avoids your having to engage in the complicated syntax of block variables).
To give you a practical example, one might infer from the name of the block type and its parameters that this defines a completion block (e.g. a block of code to be performed when some asynchronous operation, like a slow network request, completes). See Using a Block as a Method Argument.
For example, imagine that you had some InventoryManager class from which you could request product information, with a method with an interface defined like so, using your typedef:
- (void)requestProductsWithName:(NSString *)name completion:(RequestProductsCompletionHandler)completion;
And you might use the method like so:
[inventoryManager requestProductsWithName:name completion:^(BOOL success, NSArray * products) {
// when the request completes asynchronously (likely taking a bit of time), this is
// how we want to handle the response when it eventually comes in.
for (Product *product in products) {
NSLog(#"name = %#; qty = %#", product.name, product.quantity);
}
}];
// but this method carries on here while requestProductsWithName runs asynchronously
And, if you looked at the implementation of requestProductsWithName, it could conceivably look something like:
- (void)requestProductsWithName:(NSString *)name completion:(RequestProductsCompletionHandler)completion
{
// initiate some asynchronous request, e.g.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// now do some time consuming network request to get the products here
// when all done, we'll dispatch this back to the caller
dispatch_async(dispatch_get_main_queue(), {
if (products)
completion(YES, products); // success = YES, and return the array of products
else
completion(NO, nil); // success = NO, but no products to pass back
});
});
}
Clearly, this is unlikely to be precisely what your particular completion handler block is doing, but hopefully it illustrates the concept.
Mike Walker created a nice one page site that shows all possibilities to declare a block in Objective-C. This can be helpful to understand your problem as well:
http://fuckingblocksyntax.com
To quote his site, this is how you can define blocks:
As a local variable:
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
As a property:
#property (nonatomic, copy) returnType (^blockName)(parameterTypes);
As a method parameter:
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName {...}
As an argument to a method call:
[someObject someMethodThatTakesABlock: ^returnType (parameters) {...}];
As a typedef:
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^(parameters) {...}

pthread parallel processing

Need urgent help on thread: the goal here is the separtemask will take each image and separate different contours and for each contour in the image it will call handleobject thread. So every for loop will call the handeobject thread. However, object index variable needs to be passed in each thread. But only last value of objectndex is passed, this is becuase the speratemask function loops and repalces the value of obj.objindx and only the last value of obj.objindx is
passed to all the threads. Is there anyway to pass each objectindex
value in handleobject. The code runs fine if we uncomment the pthread_join(tid[objectIndex],NULL); but it will not give a parralel program
void separateMask(IplImage *maskImg)
{
for(r = contours; r != NULL; r = r->h_next)
{
cvSet(objectMaskImg, cvScalarAll(0), NULL);
CvScalar externalColor = cvScalarAll(0xff);
CvScalar holeColor = cvScalarAll(0x00);
int maxLevel = -1;
int thinkness = CV_FILLED;
int lineType = 8; /* 8-connected */
cvDrawContours(objectMaskImg, r, externalColor, holeColor, maxLevel, thinkness,lineType, cvPoint(0,0));;
obj.objectMaskImg1[objectIndex]=(IplImage *) malloc(sizeof(IplImage));
obj.objectMaskImg1[objectIndex]=objectMaskImg;
obj.objindx=objectIndex;
obj.intensityOut1=intensityOut;
obj.tasOut1=tasOut;
pthread_create(&tid[objectIndex],NULL,handleObject,(void *)&obj);
//pthread_join(tid[objectIndex],NULL);
printf("objectindx %d\n",obj.objindx);
objectIndex++;
}
// cvReleaseImage(&objectMaskImg);
//cvReleaseMemStorage(&storage);
printf("Exitng Separatemask\n");
}
void* handleObject(void *arg)
{
int i, j;
handle *hndl;
hndl=(handle *) malloc(sizeof(handle));
hndl=(handle*)arg;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&lock);
IplImage *pImg;
float statistics_ratio[3][9];
pthread_t tid3;
tas3 tas2;
pImg = cvLoadImage("image.tif", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
if(pImg == NULL)
{
fprintf(stderr, "Fail to load image %s\n", "tiff file");
return ;
}
tas2.pImg1=pImg;
printf("tst%d\n",hndl->objindx);
tas2.x=hndl->objindx;
tas2.objectMaskImg1=hndl->objectMaskImg1[tas2.x];
tas2.statistics_ratio[3][9]=statistics_ratio[3][9];
double mean = average_intensity(pImg, tas2.objectMaskImg1);
int total = total_white(pImg, tas2.objectMaskImg1);
pthread_mutex_unlock(&lock);
printf("Exiting handle object thread_id %d\n\n", pthread_self());
}
This function appears to have issues
void* handleObject(void *arg)
Firstly
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&lock);
this is a locally created mutex - but created WITHIN the thread function. So you lock it but since nothing else can see the mutex, why do you need it??? It gives no synchronization functionality if no other threads can see it.
Secondly
float statistics_ratio[3][9];
pthread_t tid3;
tas3 tas2;
pImg = cvLoadImage("image.tif", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
if(pImg == NULL){
fprintf(stderr, "Fail to load image %s\n", "tiff file");
return ;
}
tas2.pImg1=pImg;
printf("tst%d\n",hndl->objindx);
tas2.x=hndl->objindx;
tas2.objectMaskImg1=hndl->objectMaskImg1[tas2.x];
tas2.statistics_ratio[3][9]=statistics_ratio[3][9];
you create a local uninitialised 2d float array statistics_ratio, do nothing with it then assign it to another locally created object member. This appears to be meaningless, as does the declaration of another pthread instance tid3.
It doesn't really matter since nothing else can see the thread but you return from inside this function if pImg == NULL without first unlocking the mutex.
It is very hard to see why your code doesnt work or what it is meant to do, but perhaps the things highlighted above may help. You are creating a lot of local variables within your thread functions which are not being used. I am not sure if you need some of these to be global instead - particularly the mutex (if indeed you need one at all).
I think your initial problem is that you're reusing the obj structure that you're passing to the created threads so you'll have data races where the thread just created will read information that's been overwritten with data intended for another thread.
The loop that creates the threads has the following structure:
for(r = contours; r != NULL; r = r->h_next)
{
// initialize obj with information for the thread
// ...
// create a thread and pass it a pointer to obj
pthread_create(&tid[objectIndex],NULL,handleObject,(void *)&obj);
// some other bookkeeping
}
Since you immediately re-initialize obj on the next loop iteration, who knows what data the thread function is going to get? That's why things work if you join the thread after creating it - the obj structure remains stable because the loop blocks until the thread is finished.
Change the loop to look something like:
for(r = contours; r != NULL; r = r->h_next)
{
// instead of using `obj`, allocate a struct using malloc
handle* threaddata = malloc(sizeof(handle); // note: I'm not sure if `handle` is the right type
// initialize *threaddata with information for the thread
// ...
// create a thread and pass it the threaddata pointer
pthread_create(&tid[objectIndex],NULL,handleObject,threaddata);
// some other bookkeeping
}
Then free() the data in the thread function after it is finished with with (ie., the thread creation code creates and initializes the block of data then passes ownership of it to the thread).
Note that this might not be as straightforward as it often is, becuase it looks like your obj structure already has some per-thread information in it (the objectMaskImg1 element looks to be an array it each element being intended for a separate thread). So you might need to do some refactoring of the data structure as well.
Finally, there are several other outright bugs such as immediately overwriting pointers to blocks allocated by malloc():
obj.objectMaskImg1[objectIndex]=(IplImage *) malloc(sizeof(IplImage));
obj.objectMaskImg1[objectIndex]=objectMaskImg;
and
hndl=(handle *) malloc(sizeof(handle));
hndl=(handle*)arg;
In addition to the pointless use of the mutex in the handleObject() thread function as mentioned by mathematician1975 (http://stackoverflow.com/a/11460092/12711).
A fair bit of the code in the thread function (copying or attempting to copy data locally, the mutex) appears to be stuff thrown in to try to fix problems without actually understanding what the problem is. I think you really need to get an understanding of where various data lives, how to copy it (as opposed to just copying a pointer to it), and how to manage the ownership of the data.

Resources