Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
188 views
in Technique[技术] by (71.8m points)

ios - App Crashes after executing background fetch completionHandler

I have updated our app for iOS 7 and added the background fetch functionality. However, i'm noticing some crashes because of this feature. After background fetch call is completed, the completion handler block is executed with either new/no data. This results in a call to 'layoutSubviews' of my custom navigation NavigationBar and sometimes app is crashing with the following stack trace. I could not reproduce this issue myself but constantly receiving these crash logs from our users. Any help would be appreciated.

Thread 0 Crashed:
0   libsystem_platform.dylib            0x39cba486 _platform_memmove$VARIANT$Swift + 102
1   Foundation                          0x2fce8f47 -[NSData(NSData) getBytes:range:] + 419
2   CoreFoundation                      0x2f30637d CFDataGetBytes + 205
3   ImageIO                             0x300e7357 CGImageReadGetBytesAtOffset + 283
4   ImageIO                             0x300e7231 CGImageReadSessionGetBytes + 29
5   ImageIO                             0x3022baeb read_fn + 23
6   ImageIO                             0x300e7189 png_read_sig + 45
7   ImageIO                             0x300e6e0d _cg_png_read_info + 33
8   ImageIO                             0x300ef62f copyImageBlockSetPNG + 1123
9   ImageIO                             0x300eec4b ImageProviderCopyImageBlockSetCallback + 539
10  CoreGraphics                        0x2f43577d CGImageProviderCopyImageBlockSetWithOptions + 137
11  CoreGraphics                        0x2f43a145 subImageProviderCopyImageBlockSet + 305
12  CoreGraphics                        0x2f43577d CGImageProviderCopyImageBlockSetWithOptions + 137
13  CoreGraphics                        0x2f435433 img_blocks_create + 383
14  CoreGraphics                        0x2f4286fd img_data_lock + 1053
15  CoreGraphics                        0x2f427ae1 CGSImageDataLock + 89
16  libRIP.A.dylib                      0x2f774da7 ripc_AcquireImage + 99
17  libRIP.A.dylib                      0x2f774131 ripc_DrawImage + 601
18  CoreGraphics                        0x2f4279f3 CGContextDelegateDrawImage + 51
19  CoreGraphics                        0x2f427879 CGContextDrawImage + 285
20  WebCore                             0x373120db WebCore::GraphicsContext::drawNativeImage(CGImage*, WebCore::FloatSize const&, WebCore::ColorSpace, WebCore::FloatRect const&, WebCore::FloatRect const&, float, WebCore::CompositeOperator, WebCore::BlendMode, WebCore::ImageOrientation) + 1127
21  WebCore                             0x37310e79 WebCore::BitmapImage::draw(WebCore::GraphicsContext*, WebCore::FloatRect const&, WebCore::FloatRect const&, WebCore::ColorSpace, WebCore::CompositeOperator, WebCore::BlendMode, WebCore::RespectImageOrientationEnum) + 349
22  WebCore                             0x3735d897 WebCore::BitmapImage::draw(WebCore::GraphicsContext*, WebCore::FloatRect const&, WebCore::FloatRect const&, WebCore::ColorSpace, WebCore::CompositeOperator, WebCore::BlendMode) + 31
23  WebCore                             0x3735892f WebCore::Image::drawTiled(WebCore::GraphicsContext*, WebCore::FloatRect const&, WebCore::FloatPoint const&, WebCore::FloatSize const&, WebCore::ColorSpace, WebCore::CompositeOperator, WebCore::BlendMode) + 499
24  WebCore                             0x37358735 WebCore::GraphicsContext::drawTiledImage(WebCore::Image*, WebCore::ColorSpace, WebCore::IntRect const&, WebCore::IntPoint const&, WebCore::IntSize const&, WebCore::CompositeOperator, bool, WebCore::BlendMode) + 193
25  WebCore                             0x3728bc11 WebCore::RenderBoxModelObject::paintFillLayerExtended(WebCore::PaintInfo const&, WebCore::Color const&, WebCore::FillLayer const*, WebCore::LayoutRect const&, WebCore::BackgroundBleedAvoidance, WebCore::InlineFlowBox*, WebCore::LayoutSize const&, WebCore::CompositeOperator, WebCore::RenderObject*) + 3321
26  WebCore                             0x3728addd WebCore::RenderBox::paintFillLayers(WebCore::PaintInfo const&, WebCore::Color const&, WebCore::FillLayer const*, WebCore::LayoutRect const&, WebCore::BackgroundBleedAvoidance, WebCore::CompositeOperator, WebCore::RenderObject*) + 449
27  WebCore                             0x3728ab41 WebCore::RenderBox::paintBackground(WebCore::PaintInfo const&, WebCore::LayoutRect const&, WebCore::BackgroundBleedAvoidance) + 317
28  WebCore                             0x37289ee5 WebCore::RenderBox::paintBoxDecorations(WebCore::PaintInfo&, WebCore::LayoutPoint const&) + 329
29  WebCore                             0x3728806f WebCore::RenderBlock::paintObject(WebCore::PaintInfo&, WebCore::LayoutPoint const&) + 55
30  WebCore                             0x37289c3f WebCore::RenderBlock::paint(WebCore::PaintInfo&, WebCore::LayoutPoint const&) + 187
31  WebCore                             0x37288cc9 WebCore::RenderBlock::paintFloats(WebCore::PaintInfo&, WebCore::LayoutPoint const&, bool) + 305
32  WebCore                             0x3728813d WebCore::RenderBlock::paintObject(WebCore::PaintInfo&, WebCore::LayoutPoint const&) + 261
33  WebCore                             0x37289c3f WebCore::RenderBlock::paint(WebCore::PaintInfo&, WebCore::LayoutPoint const&) + 187
34  WebCore                             0x37288cfb WebCore::RenderBlock::paintFloats(WebCore::PaintInfo&, WebCore::LayoutPoint const&, bool) + 355
35  WebCore                             0x3728813d WebCore::RenderBlock::paintObject(WebCore::PaintInfo&, WebCore::LayoutPoint const&) + 261
36  WebCore                             0x37289c3f WebCore::RenderBlock::paint(WebCore::PaintInfo&, WebCore::LayoutPoint const&) + 187
37  WebCore                             0x37288861 WebCore::RenderLayer::paintForegroundForFragmentsWithPhase(WebCore::PaintPhase, WTF::Vector<WebCore::LayerFragment, 1ul, WTF::CrashOnOverflow> const&, WebCore::GraphicsContext*, WebCore::RenderLayer::LayerPaintingInfo const&, unsigned int, WebCore::RenderObject*) + 269
38  WebCore                             0x372886e7 WebCore::RenderLayer::paintForegroundForFragments(WTF::Vector<WebCore::LayerFragment, 1ul, WTF::CrashOnOverflow> const&, WebCore::GraphicsContext*, WebCore::GraphicsContext*, WebCore::LayoutRect const&, bool, WebCore::RenderLayer::LayerPaintingInfo const&, unsigned int, WebCore::RenderObject*, bool, bool) + 235
39  WebCore                             0x37286435 WebCore::RenderLayer::paintLayerContents(WebCore::GraphicsContext*, WebCore::RenderLayer::LayerPaintingInfo const&, unsigned int) + 1585
40  WebCore                             0x37285ca9 WebCore::RenderLayer::paintLayer(WebCore::GraphicsContext*, WebCore::RenderLayer::LayerPaintingInfo const&, unsigned int) + 621
41  WebCore                             0x372885d9 WebCore::RenderLayer::paintList(WTF::Vector<WebCore::RenderLayer*, 0ul, WTF::CrashOnOverflow>*, WebCore::GraphicsContext*, WebCore::RenderLayer::LayerPaintingInfo const&, unsigned int) + 101
42  WebCore                             0x3728647f WebCore::RenderLayer::paintLayerContents(WebCore::GraphicsContext*, WebCore::RenderLayer::LayerPaintingInfo const&, unsigned int) + 1659
43  WebCore                             0x37285ca9 WebCore::RenderLayer::paintLayer(WebCore::GraphicsContext*, WebCore::RenderLayer::LayerPaintingInfo const&, unsigned int) + 621
44  WebCore                             0x372885d9 WebCore::RenderLayer::paintList(WTF::Vector<WebCore::RenderLayer*, 0ul, WTF::CrashOnOverflow>*, WebCore::GraphicsContext*, WebCore::RenderLayer::LayerPaintingInfo const&, unsigned int) + 101
45  WebCore                             0x3728647f WebCore::RenderLayer::paintLayerContents(WebCore::GraphicsContext*, WebCore::RenderLayer::LayerPaintingInfo const&, unsigned int) + 1659
46  WebCore                             0x37285ca9 WebCore::RenderLayer::paintLayer(WebCore::GraphicsContext*, WebCore::RenderLayer::LayerPaintingInfo const&, unsigned int) + 621
47  WebCore                             0x372859b3 WebCore::RenderLayer::paint(WebCore::GraphicsContext*, WebCore::LayoutRect const&, unsigned int, WebCore::RenderObject*, WebCore::RenderRegion*, unsigned int) + 103
48  WebCore                             0x3728541b WebCore::FrameView::paintContents(WebCore::GraphicsContext*, WebCore::IntRect const&) + 499
49  WebKit                              0x37c4578d -[WebFrame(WebInternal) _drawRect:contentsOnly:] + 357
50  WebKit                              0x37c455b9 -[WebHTMLView drawSingleRect:] + 137
51  WebKit                              0x37c454db -[WebHTMLView drawRect:] + 43
52  WebCore                             0x37284d93 -[WAKView _drawRect:context:lockFocus:] + 275
53  WebCore                             0x37284ec7 -[WAKView _drawRect:context:lockFocus:] + 583
54  WebCore                             0x37284ec7 -[WAKView _drawRect:context:lockFocus:] + 583
55  WebCore                             0x37284ec7 -[WAKView _drawRect:context:lockFocus:] + 583
56  WebCore                             0x37284ec7 -[WAKView _drawRect:context:lockFocus:] + 583
57  WebCore                             0x37284c47 -[WAKView displayRect:] + 59
58  WebCore                             0x37284c03 -[WAKWindow displayRect:] + 55
59  WebCore                             0x37284b49 WebCore::TileCache::drawWindowContent(TileLayer*, CGContext*, CGRect) + 673
60  WebCore                             0x37284525 WebCore::TileCache::drawLayer(TileLayer*, CGContext*) + 505
61  QuartzCore                          0x317d3813 CABackingStoreUpdate_ + 1859
62  QuartzCore                          0x318ad735 ___ZN2CA5Layer8display_Ev_block_invoke + 53
63  QuartzCore                          0x317d30c3 x_blame_allocations + 83
64  QuartzCore                          0x317d2d77 CA::Layer::display_() + 1119
65  QuartzCore                          0x317b6969 CA::Layer::display_if_needed(CA::Transaction*) + 209
66  QuartzCore                          0x317b6601 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 25
67  QuartzCore                          0x317b600d CA::Context::commit_transaction(CA::Transaction*) + 229
68  QuartzCore                          0x317b5e1f CA::Transaction::commit() + 315
69  UIKit                               0x31d973c9 _UIWindowUpdateVisibleContextOrder + 209
70  UIKit                               0x31d9729d +[UIWindow _prepareWindowsPassingTestForAppResume:] + 13
71  UIKit                               0x31db0ac5 -[UIApplication _updateSnapshotAndStateRestorationArchiveForBackgroundEvent:saveState:exitIfCouldNotRestoreState:] + 201
72  UIKit                               0x31db0d81 -[UIApplication _replyToBackgroundFetchRequestWithResult:remoteNotificationToken:sequenceNumber:updateApplicationSnapshot:] + 105
73  UIKit                               0x31db138d __61-[UIApplication _handleOpportunisticFetchWithSequenceNumber:]_block_invoke + 37
74  MyApp                               0x001456b7 -[List fetched:error:withBackgroundFetchCompletionHandler:] (List.m:421)
75  MyApp                               0x00144f87 __71-[List fetchFromServerWithBackgroundFetchCompletionHandler:]_block_invoke (List.m:292)
76  MyApp                               0x0021ed07 APICompletionBlock_block_invoke_6 (APIRequest.m:305)
77  libdispatch.dylib                   0x39b8c103 _dispatch_call_block_and_release + 11
78  libdispatch.dylib                   0x39b8c0ef _dispatch_client_callout + 23
79  libdispatch.dylib                   0x39b8e9a9 _dispatch_main_queue_callback_4CF + 269
80  CoreFoundation                      0x2f3785b9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
81  CoreFoundation                      0x2f376e85 __CFRunLoopRun + 1309
82  CoreFoundation            

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When you leave your app to the background, it saves the snapshot of the current view to the memory so it could be shown when you double-click the home button. With the iOS7 background refresh feature ((void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler), you must execute the completionHandler function after you finish executing your fetch request.

The execution of that function also triggers updates to the UI - [UIApplication _updateSnapshotAndStateRestorationArchiveForBackgroundEvent:saveState:exitIfCouldNotRestoreState:], and in your case it triggers calculating the frame for a UIWebView from a background thread. UIWebView can be updated only from the UIThread, so to overcome this crash I would suggest to wrap the completionHandler with execution on the main thread:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
    void (^safeHandler)(UIBackgroundFetchResult) = ^(UIBackgroundFetchResult result){
        dispatch_async(dispatch_get_main_queue(), ^{
            completionHandler(result);
        });
    };
    [someInstance doSomethingInBackground:userInfo withHandler:safeHandler];
}

And you will no longer have to worry where you invoke the completionHandler (now safeHandler) from.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...