Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deadlock with GCD and webView

I've found an issue that seems to be causing a deadlock in WebKit. If I run this code from my main thread, I rightly see an alert. I can tap on the "OK" button on the alert and it dismisses and all is working well:

[theWebView stringByEvaluatingJavaScriptFromString:@"alert('hi');"];

If I make a slight modification, then the alert message still appears, but the OK button cannot be tapped on - you cannot dismiss the alert and if you break into the app it is hung in the stringByEvaluatingJavaScriptFromString call:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        [theWebView stringByEvaluatingJavaScriptFromString:@"alert('hi');"];
    });
});

The only different in these two is that in the second one, it is running the JS in the main thread in the context of a dispatch queue.

On the other hand, if I do the following, then the hang does not occur:

- (void) showHi:(id) it
{
    [(UIWebView*)it stringByEvaluatingJavaScriptFromString:@"alert('hi');"];
}

....

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self performSelectorOnMainThread:@selector(showHi:) withObject:theWebView waitUntilDone:NO];
});

Can someone shine some light on what is going wrong to cause the hang?

EDIT:

Related questions:

Perform UI Changes on main thread using dispatch_async or performSelectorOnMainThread?
Whats the difference between performSelectorOnMainThread and dispatch_async on main queue?
Grand Central Dispatch (GCD) vs. performSelector - need a better explanation

Very similar question:

UIWebView stringByEvaluatingJavaScriptFromString hangs on iOS5.0/5.1 when called using GCD

like image 812
1800 INFORMATION Avatar asked Oct 23 '13 02:10

1800 INFORMATION


1 Answers

I think it was stated in webview Image class reference

Now, For your case of dead lock you can simulate the same by replacing this [self performSelectorOnMainThread:@selector(showHi:) withObject:theWebView waitUntilDone:NO];

with

performSelector:withObject:afterDelay:inModes: . With Respective mode by default it was NSDefaultRunLoopMode and which was atomic in nature whereas in your nonatomic case of dispatch_get_main_queue() you have to change the current dispatch mode of threading.

I hope it remained informative. Also, more suggestions are welcomed.

like image 60
itechnician Avatar answered Sep 22 '22 14:09

itechnician