From 21ced682547ef855ac6d83a00ad7fda1b8225af3 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 23 Dec 2014 13:14:06 +0100 Subject: Fix two threading issues * A call of setString: from background thread which could cause a "deleted thread with uncommitted CATransaction" warning * SPFieldMapperController was allocated from a background thread with an own autoreleasepool, while it contains UI objects. This could cause a crash when the autoreleasepool was drained and the field mapper forcefully released, while other UI objects still had it retained. --- Source/SPDataImport.m | 54 +++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 25 deletions(-) (limited to 'Source/SPDataImport.m') diff --git a/Source/SPDataImport.m b/Source/SPDataImport.m index b0355b05..5859b75d 100644 --- a/Source/SPDataImport.m +++ b/Source/SPDataImport.m @@ -754,7 +754,7 @@ if ([csvFileHandle compressionFormat] == SPBzip2Compression) useIndeterminate = YES; // Reset progress interface - [errorsView setString:@""]; + [[errorsView onMainThread] setString:@""]; [[singleProgressTitle onMainThread] setStringValue:NSLocalizedString(@"Importing CSV", @"text showing that the application is importing CSV")]; [[singleProgressText onMainThread] setStringValue:NSLocalizedString(@"Reading...", @"text showing that app is reading dump")]; [[singleProgressBar onMainThread] setIndeterminate:YES]; @@ -1240,29 +1240,33 @@ fieldMapperSheetStatus = SPFieldMapperInProgress; fieldMappingArrayHasGlobalVariables = NO; - // Init the field mapper controller - fieldMapperController = [(SPFieldMapperController *)[SPFieldMapperController alloc] initWithDelegate:self]; - [fieldMapperController setConnection:mySQLConnection]; - [fieldMapperController setSourcePath:filename]; - [fieldMapperController setImportDataArray:fieldMappingImportArray hasHeader:[importFieldNamesSwitch state] isPreview:fieldMappingImportArrayIsPreview]; - - // Show field mapper sheet and set the focus to it - [[NSApp onMainThread] beginSheet:[fieldMapperController window] - modalForWindow:[tableDocumentInstance parentWindow] - modalDelegate:self - didEndSelector:@selector(fieldMapperDidEndSheet:returnCode:contextInfo:) - contextInfo:nil]; - - [[[fieldMapperController window] onMainThread] makeKeyWindow]; + //the field mapper is an UI object and must not be caught in the background thread's autoreleasepool + dispatch_async(dispatch_get_main_queue(), ^{ + // Init the field mapper controller + fieldMapperController = [[SPFieldMapperController alloc] initWithDelegate:self]; + [fieldMapperController setConnection:mySQLConnection]; + [fieldMapperController setSourcePath:filename]; + [fieldMapperController setImportDataArray:fieldMappingImportArray hasHeader:[importFieldNamesSwitch state] isPreview:fieldMappingImportArrayIsPreview]; + + // Show field mapper sheet and set the focus to it + [NSApp beginSheet:[fieldMapperController window] + modalForWindow:[tableDocumentInstance parentWindow] + modalDelegate:self + didEndSelector:@selector(fieldMapperDidEndSheet:returnCode:contextInfo:) + contextInfo:nil]; + + [[fieldMapperController window] makeKeyWindow]; + }); // Wait for field mapper sheet while (fieldMapperSheetStatus == SPFieldMapperInProgress) usleep(100000); + + BOOL success = NO; // If the mapping was cancelled, abort the import if (fieldMapperSheetStatus == SPFieldMapperCancelled) { - if (fieldMapperController) [fieldMapperController release]; - return NO; + goto cleanup; } // Get mapping settings and preset some global variables @@ -1288,9 +1292,8 @@ || ![selectedTableTarget length] || ![csvImportHeaderString length]) { - if(fieldMapperController) [fieldMapperController release]; NSBeep(); - return NO; + goto cleanup; } // Store target table definitions @@ -1312,13 +1315,14 @@ [importFieldNamesSwitch setState:[fieldMapperController importFieldNamesHeader]]; [prefs setBool:[importFieldNamesSwitch state] forKey:SPCSVImportFirstLineIsHeader]; + success = YES; + +cleanup: + dispatch_async(dispatch_get_main_queue(), ^{ + if(fieldMapperController) [fieldMapperController release], fieldMapperController = nil; + }); - if(fieldMapperController) [fieldMapperController release]; - - if(fieldMapperSheetStatus == SPFieldMapperCompleted) - return YES; - else - return NO; + return success; } /** -- cgit v1.2.3