Skip to content
This repository has been archived by the owner on Aug 11, 2020. It is now read-only.

iOS WebThreadLock crash on barcodeScanFailed #310

Closed
JohnBrooking opened this issue Aug 25, 2016 · 9 comments
Closed

iOS WebThreadLock crash on barcodeScanFailed #310

JohnBrooking opened this issue Aug 25, 2016 · 9 comments
Labels

Comments

@JohnBrooking
Copy link

I recently upgraded to 6.0.1 from a much older version (~2013), and have begun experiencing an occasional crash on iPhone, especially when scanning in landscape mode.

I think I may have figured it out, but I'm pretty new to iOS and mobile programming, and am only reading about dispatch queues this morning! (I did not write the app I'm working on, just modifying it.)

The debugger message is

bool _WebTryThreadLock(bool), 0x15531220: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...

The top section of the call stack is

1   0x2836cee7 WebThreadLock
2   0x2968ea11 <redacted>
3   0x92811 -[CDVViewController shouldAutorotateToInterfaceOrientation:]
4   0xa0dd5 -[MainViewController shouldAutorotateToInterfaceOrientation:]
5   0x92903 -[CDVViewController supportedInterfaceOrientations]
6   0x2929ca67 <redacted>
7   0x2929c581 <redacted>
8   0x29321d9d <redacted>
9   0x29abed37 <redacted>
10  0x29574bdd <redacted>
11  0x2959a6d5 <redacted>
12  0x29358aef <redacted>
13  0x292fcd19 <redacted>
14  0x29599a89 <redacted>
15  0x292fc8bd <redacted>
16  0xa2a3f -[CDVbcsProcessor barcodeScanDone:]
17  0xa30bf -[CDVbcsProcessor barcodeScanFailed:]

The actual line that's crashing is in source file CDFVViewController.m, on the line where res is set to the result of the webView.stringByEvaluatingJavaScriptFromString method (last line of this snippet):

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // First, ask the webview via JS if it supports the new orientation
    NSString* jsCall = [NSString stringWithFormat:
        @"window.shouldRotateToOrientation && window.shouldRotateToOrientation(%ld);"
        , (long)[self mapIosOrientationToJsOrientation:interfaceOrientation]];
    NSString* res = [webView stringByEvaluatingJavaScriptFromString:jsCall];

To help debug, I put in logging statements at the begin and end of all of the orientation-related methods, as well as "captureOutput", and noticed this interesting thing:

2016-08-23 13:10:44.953 Sappi Stock Manager[2412:1225939] begin CDVViewController.shouldAutorotateToInterfaceOrientation
2016-08-23 13:10:44.953 Sappi Stock Manager[2412:1225939] about to return from CDVViewController.shouldAutorotateToInterfaceOrientation
2016-08-23 13:10:44.954 Sappi Stock Manager[2412:1225939] begin CDVViewController.shouldAutorotateToInterfaceOrientation
2016-08-23 13:10:44.954 Sappi Stock Manager[2412:1225939] about to return from CDVViewController.shouldAutorotateToInterfaceOrientation
2016-08-23 13:10:45.450 Sappi Stock Manager[2412:1225939] Orientation change event.
2016-08-23 13:10:45.450 Sappi Stock Manager[2412:1225939] Footer positioned at: 528
2016-08-23 13:10:45.451 Sappi Stock Manager[2412:1225939] Subtracting menu height of: 50
2016-08-23 13:10:45.451 Sappi Stock Manager[2412:1225939] Calculated final height of: 518
2016-08-23 13:10:46.851 Sappi Stock Manager[2412:1225972] Inside captureOutput
2016-08-23 13:10:47.263 Sappi Stock Manager[2412:1225972] begin CDVViewController.shouldAutorotateToInterfaceOrientation
2016-08-23 13:10:47.264 Sappi Stock Manager[2412:1225972] bool _WebTryThreadLock(bool), 0x15531220: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...

All prior calls to CDVViewController.shouldAutorotateToInterfaceOrientation take place on thread 1225939, with the statement "Inside captureOutput" taking place on various other threads. But notice that the call to CDVViewController.shouldAutorotateToInterfaceOrientation which fails occurs on thread 1225972, the same thread as the last "Inside captureOutput" statement!

I'm assuming 1225939 is the main thread, and captureOutput gets called in a secondary thread. I see in CDVbcsProcessor.setupCaptureSession:

[output setSampleBufferDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)];

Then I see in CDVbcsProcessor.barcodeScanSucceeded:

- (void)barcodeScanSucceeded:(NSString*)text format:(NSString*)format {
    dispatch_sync(dispatch_get_main_queue(), ^{
        [self barcodeScanDone:^{
            [self.plugin returnSuccess:text format:format cancelled:FALSE flipped:FALSE callback:self.callback];
        }];
        AudioServicesPlaySystemSound(_soundFileObject);
    });
}

But CDVbcsProcessor.barcodeScanFailed does not dispatch back to the main thread:

- (void)barcodeScanFailed:(NSString*)message {
    [self barcodeScanDone:^{
        [self.plugin returnError:message callback:self.callback];
    }];
}

I feel like this is the problem, and I'm going to test that now. I'll update this note after I see what that does.

@JohnBrooking
Copy link
Author

I am happy to report that I appear to have fixed the problem!

I simply replaced this code in CDVBarcodeScanner.mm

- (void)barcodeScanFailed:(NSString*)message {
    [self barcodeScanDone:^{
        [self.plugin returnError:message callback:self.callback];
    }];

with

- (void)barcodeScanFailed:(NSString*)message {
    dispatch_sync(dispatch_get_main_queue(), ^{
        [self barcodeScanDone:^{
            [self.plugin returnError:message callback:self.callback];
        }];
    });
}

I confirmed that when barcodeScanFailed is called now (which it still is sometimes, but that's a different issue), it is still in the same secondary thread as the capture session, but its call of barcodeScanDone now takes place in the main thread, as do all succeeding calls to the orientation-related view methods. So now the scan failure is just handled normally, not by crashing.

@EddyVerbruggen
Copy link
Collaborator

@JohnBrooking That's great news! Are you up for a little PR with that change?

@JohnBrooking
Copy link
Author

Sure, if you agree that it's correct.

@EddyVerbruggen
Copy link
Collaborator

I do, it makes a lot of sense to me. That and the fact you no longer see the crash 😉

@ignacio-chiazzo
Copy link

@JohnBrooking @EddyVerbruggen I didn't see the JohnBrooking's PR nor the closed PR's

@macdonst
Copy link
Member

@JohnBrooking thanks John, I see you never sent a PR so I added it into the plugin for you.

@JohnBrooking
Copy link
Author

Thanks, guys. Sorry I dropped it. I'm new to Github/open source, and I didn't know "PR" meant I was supposed to do something. 😊

@macdonst
Copy link
Member

No problem @JohnBrooking. The nice thing about open source is if you find a bug you can always send a pull request.

@lock
Copy link

lock bot commented Jun 8, 2018

This thread has been automatically locked.

@lock lock bot locked as resolved and limited conversation to collaborators Jun 8, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

No branches or pull requests

4 participants