From 27fa5dc2ef91aa317efede67a1ec791fdba364f7 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 5 Sep 2018 16:56:19 -0400 Subject: [PATCH] Make thumbnail logic thread-safe to being called on main thread. --- .../Attachments/OWSThumbnailService.swift | 7 ++--- .../Messages/Attachments/TSAttachmentStream.m | 31 ++++++++++++++----- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/SignalServiceKit/src/Messages/Attachments/OWSThumbnailService.swift b/SignalServiceKit/src/Messages/Attachments/OWSThumbnailService.swift index 680492211..77e7353a3 100644 --- a/SignalServiceKit/src/Messages/Attachments/OWSThumbnailService.swift +++ b/SignalServiceKit/src/Messages/Attachments/OWSThumbnailService.swift @@ -85,8 +85,7 @@ private struct OWSThumbnailRequest { return attachment.isImage || attachment.isAnimated || attachment.isVideo } - // completion will only be called on success. - // completion will be called async on the main thread. + // success and failure will be called async _off_ the main thread. @objc public func ensureThumbnail(forAttachment attachment: TSAttachmentStream, thumbnailDimensionPoints: UInt, @@ -114,13 +113,13 @@ private struct OWSThumbnailRequest { do { let loadedThumbnail = try process(thumbnailRequest: thumbnailRequest) - DispatchQueue.main.async { + DispatchQueue.global().async { thumbnailRequest.success(loadedThumbnail) } } catch { Logger.error("Could not create thumbnail: \(error)") - DispatchQueue.main.async { + DispatchQueue.global().async { thumbnailRequest.failure(error) } } diff --git a/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m b/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m index e856d18bd..e6d7f301b 100644 --- a/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m +++ b/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m @@ -7,6 +7,7 @@ #import "NSData+Image.h" #import "OWSFileSystem.h" #import "TSAttachmentPointer.h" +#import "Threading.h" #import #import #import @@ -694,10 +695,16 @@ typedef void (^OWSLoadedThumbnailSuccess)(OWSLoadedThumbnail *loadedThumbnail); { OWSLoadedThumbnail *_Nullable loadedThumbnail; loadedThumbnail = [self loadedThumbnailWithThumbnailDimensionPoints:thumbnailDimensionPoints - success:^(OWSLoadedThumbnail *loadedThumbnail) { - success(loadedThumbnail.image); - } - failure:failure]; + success:^(OWSLoadedThumbnail *loadedThumbnail) { + DispatchMainThreadSafe(^{ + success(loadedThumbnail.image); + }); + } + failure:^{ + DispatchMainThreadSafe(^{ + failure(); + }); + }]; return loadedThumbnail.image; } @@ -737,7 +744,7 @@ typedef void (^OWSLoadedThumbnailSuccess)(OWSLoadedThumbnail *loadedThumbnail); - (nullable OWSLoadedThumbnail *)loadedThumbnailSmallSync { - __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); __block OWSLoadedThumbnail *_Nullable asyncLoadedThumbnail = nil; OWSLoadedThumbnail *_Nullable syncLoadedThumbnail = nil; @@ -765,13 +772,23 @@ typedef void (^OWSLoadedThumbnailSuccess)(OWSLoadedThumbnail *loadedThumbnail); - (nullable UIImage *)thumbnailImageSmallSync { - return [self loadedThumbnailSmallSync].image; + OWSLoadedThumbnail *_Nullable loadedThumbnail = [self loadedThumbnailSmallSync]; + if (!loadedThumbnail) { + DDLogInfo(@"Couldn't load small thumbnail sync."); + return nil; + } + return loadedThumbnail.image; } - (nullable NSData *)thumbnailDataSmallSync { + OWSLoadedThumbnail *_Nullable loadedThumbnail = [self loadedThumbnailSmallSync]; + if (!loadedThumbnail) { + DDLogInfo(@"Couldn't load small thumbnail sync."); + return nil; + } NSError *error; - NSData *_Nullable data = [[self loadedThumbnailSmallSync] dataAndReturnError:&error]; + NSData *_Nullable data = [loadedThumbnail dataAndReturnError:&error]; if (error || !data) { OWSFail(@"Couldn't load thumbnail data: %@", error); return nil;