Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone app crashes on WebThread MPVolumeSlider

It seems like very broad to ask a question, but this is very annoying and difficult to fix the bug.

Here's the crash log for WebThread which I got from Crashlytics.

Thread : Crashed: WebThread
0  libobjc.A.dylib                0x0000000193e97bd0 objc_msgSend + 16
1  UIKit                          0x0000000187f65dd8 +[UIViewAnimationState  popAnimationState] + 332
2  MediaPlayer                    0x0000000185953358 -[MPVolumeSlider volumeController:volumeValueDidChange:] + 92
3  MediaPlayer                    0x00000001859c5fc4 -[MPVolumeController updateVolumeValue] + 260
4  MediaPlayer                    0x0000000185952cb0 -[MPVolumeSlider didMoveToSuperview] + 144
5  UIKit                          0x0000000187f2c1dc -[UIView(Hierarchy) _postMovedFromSuperview:] + 484
6  UIKit                          0x0000000187f37cbc -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1764
7  MediaPlayer                    0x0000000185955f54 -[MPVolumeView _createSubviews] + 264
8  MediaPlayer                    0x00000001859549d4 -[MPVolumeView _initWithStyle:] + 240
9  MediaPlayer                    0x0000000185954a60 -[MPVolumeView initWithFrame:style:] + 88
10 WebCore                        0x0000000191ba4684 -[WebMediaSessionHelper initWithCallback:] + 132
11 WebCore                        0x0000000191ba3db8 WebCore::MediaSessionManageriOS::MediaSessionManageriOS() + 96
12 WebCore                        0x0000000191ba3d28 WebCore::MediaSessionManager::sharedManager() + 56
13 WebCore                        0x0000000191ba2890 WebCore::MediaSession::MediaSession(WebCore::MediaSessionClient&) + 44
14 WebCore                        0x00000001916e8604 WebCore::HTMLMediaSession::create(WebCore::MediaSessionClient&) + 36
15 WebCore                        0x00000001916d0fb0 WebCore::HTMLMediaElement::HTMLMediaElement(WebCore::QualifiedName const&, WebCore::Document&, bool) + 1100
16 WebCore                        0x000000019170a2b4 WebCore::HTMLVideoElement::create(WebCore::QualifiedName const&, WebCore::Document&, bool) + 68
17 WebCore                        0x00000001916bdd9c WebCore::videoConstructor(WebCore::QualifiedName const&, WebCore::Document&, WebCore::HTMLFormElement*, bool) + 92

I never seen this kind of crash during development(I would be very happy when I can catch it with breakpoint and console log), but only appears to users when it is on live.

Can be only reported by crashlytics.

Possible reason;

App uses MagicalRecord and get data from server in background when start up. This uses multi-thread, and when webkit is using UIKit part and locking, another main thread seems like access it. So I have tried to remove all dispatch_sync and changed it to dispatch_async but the crashes happens again after proceeding a few functional calls.

What I want to know is, why WebCore is running, and I never requested MPVolumeController on UIWebView.

Even they can run on background for some reason, why it crashes? It is happening frequently and users complaint.

Any others have same problem?

like image 765
vichevstefan Avatar asked Apr 08 '15 19:04

vichevstefan


1 Answers

This bug occurred since iOS 8.

UIWebView that loads HTML containing audio or video elements will crash randomly.

I fixed it like this:

@interface H5WebKitBugsManager : NSObject

+ (void)fixAllBugs;

@end


#import "H5WebKitBugsManager.h"
#import <objc/runtime.h>

void H5Swizzle(Class c, SEL orig, SEL new)
{
    Method origMethod = class_getInstanceMethod(c, orig);
    Method newMethod = class_getInstanceMethod(c, new);
    if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
        class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    } else {
        method_exchangeImplementations(origMethod, newMethod);
    }
}

@implementation H5WebKitBugsManager

+ (void)fixAllBugs
{
    [self fixBug_MediaPlayerVolumeView];
}

+ (void)fixBug_MediaPlayerVolumeView
{
    CGFloat systemVersion = [UIDevice currentDevice].systemVersion.floatValue;

    if (systemVersion < 8.0f || systemVersion > 9.1) {
    // below ios version 8.0 has no VolumeView
        return;
    }

    Class cls = NSClassFromString(@"WebMediaSessionHelper");
    NSString *allocateVolumeView = @"allocateVolumeView";
    SEL orig = NSSelectorFromString(allocateVolumeView);
    SEL new = @selector(H5WKBMAllocateVolumeView);
    Method newMethod = class_getInstanceMethod(self, new);

    if(class_addMethod(cls, new, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
        H5Swizzle(cls, orig, new);
    }
}

- (void)H5WKBMAllocateVolumeView
{
    // WebKit's MediaSessionManageriOS is a singleton,in MediaSessionManageriOS.m. svn version181,859.
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
            // must be dispatch in background thread
            [self H5WKBMAllocateVolumeView];
        });
    });
}

@end
like image 198
wenhong chen Avatar answered Oct 29 '22 19:10

wenhong chen