From 947afd2f3380b0525cf59447a21a94886a4c7cf4 Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Thu, 7 Jan 2016 14:27:18 +0100 Subject: [PATCH] Fix NSURLSession memory leak in Swift apps This should fix the issue raised in https://github.com/bitstadium/HockeySDK-iOS/issues/237 Tested the changes before the patch with Instruments and also after the patch which prooved the leaks going away. --- Classes/BITAuthenticator.m | 10 ++++++++-- Classes/BITCrashManager.m | 4 +++- Classes/BITFeedbackListViewController.m | 10 ++++++++-- Classes/BITFeedbackManager.m | 5 ++++- Classes/BITHockeyManager.m | 4 +++- Classes/BITStoreUpdateManager.m | 5 ++++- Classes/BITUpdateManager.m | 2 ++ 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Classes/BITAuthenticator.m b/Classes/BITAuthenticator.m index 497d9cc7c0..f3baa4d61f 100644 --- a/Classes/BITAuthenticator.m +++ b/Classes/BITAuthenticator.m @@ -349,11 +349,14 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44}; if (isSessionSupported) { NSURLRequest *request = [self.hockeyAppClient requestWithMethod:@"GET" path:validationPath parameters:[self validationParameters]]; NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; + __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { typeof (self) strongSelf = weakSelf; + + [session finishTasksAndInvalidate]; + [strongSelf handleValidationResponseWithData:data error:error completion:completion]; }]; [task resume]; @@ -478,12 +481,15 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44}; __weak typeof (self) weakSelf = self; if(isURLSessionSupported) { NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; + __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { typeof (self) strongSelf = weakSelf; NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response; + + [session finishTasksAndInvalidate]; + [strongSelf handleAuthenticationWithResponse:httpResponse email:email data:data completion:completion]; }]; [task resume]; diff --git a/Classes/BITCrashManager.m b/Classes/BITCrashManager.m index 7305f6329c..d9bd535664 100644 --- a/Classes/BITCrashManager.m +++ b/Classes/BITCrashManager.m @@ -1664,7 +1664,7 @@ static void uncaught_cxx_exception_handler(const BITCrashUncaughtCXXExceptionInf id nsurlsessionClass = NSClassFromString(@"NSURLSessionUploadTask"); if (nsurlsessionClass && !bit_isRunningInAppExtension()) { NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; + __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; NSURLRequest *request = [self requestWithBoundary:kBITHockeyAppClientBoundary]; NSData *data = [self postBodyWithXML:xml attachment:attachment boundary:kBITHockeyAppClientBoundary]; @@ -1676,6 +1676,8 @@ static void uncaught_cxx_exception_handler(const BITCrashUncaughtCXXExceptionInf completionHandler:^(NSData *responseData, NSURLResponse *response, NSError *error) { typeof (self) strongSelf = weakSelf; + [session finishTasksAndInvalidate]; + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response; NSInteger statusCode = [httpResponse statusCode]; [strongSelf processUploadResultWithFilename:filename responseData:responseData statusCode:statusCode error:error]; diff --git a/Classes/BITFeedbackListViewController.m b/Classes/BITFeedbackListViewController.m index 5291cd65f1..139b9f2aba 100644 --- a/Classes/BITFeedbackListViewController.m +++ b/Classes/BITFeedbackListViewController.m @@ -720,11 +720,14 @@ id nsurlsessionClass = NSClassFromString(@"NSURLSessionDataTask"); if (nsurlsessionClass && !bit_isRunningInAppExtension()) { NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; + __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { typeof (self) strongSelf = weakSelf; + + [session finishTasksAndInvalidate]; + [strongSelf handleResponseForAttachment:attachment responseData:data error:error]; }]; [task resume]; @@ -991,12 +994,15 @@ id nsurlsessionClass = NSClassFromString(@"NSURLSessionDataTask"); if (nsurlsessionClass && !bit_isRunningInAppExtension()) { NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; + __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ typeof (self) strongSelf = weakSelf; + + [session finishTasksAndInvalidate]; + [strongSelf previewController:blockController updateAttachment:attachment data:data]; }); }]; diff --git a/Classes/BITFeedbackManager.m b/Classes/BITFeedbackManager.m index c2c2b31497..6b0aa49a77 100644 --- a/Classes/BITFeedbackManager.m +++ b/Classes/BITFeedbackManager.m @@ -950,11 +950,14 @@ NSString *const kBITFeedbackUpdateAttachmentThumbnail = @"BITFeedbackUpdateAttac id nsurlsessionClass = NSClassFromString(@"NSURLSessionDataTask"); if (nsurlsessionClass && !bit_isRunningInAppExtension()) { NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; + __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { typeof (self) strongSelf = weakSelf; + + [session finishTasksAndInvalidate]; + [strongSelf handleFeedbackMessageResponse:response data:data error:error completion:completionHandler]; }]; [task resume]; diff --git a/Classes/BITHockeyManager.m b/Classes/BITHockeyManager.m index d6857e337d..1dded36dc5 100644 --- a/Classes/BITHockeyManager.m +++ b/Classes/BITHockeyManager.m @@ -545,10 +545,12 @@ bitstadium_info_t bitstadium_library_info __attribute__((section("__TEXT,__bit_h id nsurlsessionClass = NSClassFromString(@"NSURLSessionUploadTask"); if (nsurlsessionClass && !bit_isRunningInAppExtension()) { NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; + __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; NSURLRequest *request = [[self hockeyAppClient] requestWithMethod:@"POST" path:integrationPath parameters:params]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { + [session finishTasksAndInvalidate]; + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response; [self logPingMessageForStatusCode:httpResponse.statusCode]; }]; diff --git a/Classes/BITStoreUpdateManager.m b/Classes/BITStoreUpdateManager.m index 5a99e7531f..0f9e352a0e 100644 --- a/Classes/BITStoreUpdateManager.m +++ b/Classes/BITStoreUpdateManager.m @@ -356,11 +356,14 @@ id nsurlsessionClass = NSClassFromString(@"NSURLSessionUploadTask"); if (nsurlsessionClass && !bit_isRunningInAppExtension()) { NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; + __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { typeof (self) strongSelf = weakSelf; + + [session finishTasksAndInvalidate]; + [strongSelf handleResponeWithData:data error:error]; }]; [task resume]; diff --git a/Classes/BITUpdateManager.m b/Classes/BITUpdateManager.m index e2b1c03937..43b194c665 100644 --- a/Classes/BITUpdateManager.m +++ b/Classes/BITUpdateManager.m @@ -1205,6 +1205,8 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { dispatch_async(dispatch_get_main_queue(), ^{ + [session finishTasksAndInvalidate]; + if(error){ [self handleError:error]; }else{