Skip to content

Commit

Permalink
Merge pull request #80 from abbeycode/swift-mem-leak
Browse files Browse the repository at this point in the history
Fix memory leak when using extractBufferedData from Swift
  • Loading branch information
abbeycode authored Nov 5, 2018
2 parents f9fb426 + 2ee3a1c commit d6481c5
Showing 1 changed file with 20 additions and 25 deletions.
45 changes: 20 additions & 25 deletions Classes/URKArchive.mm
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ - (instancetype)initWithFile:(NSURL *)fileURL password:(NSString*)password error
@property (assign) struct RAROpenArchiveDataEx *flags;

@property (strong) NSData *fileBookmark;
@property (strong) BOOL(^bufferedReadBlock)(NSData *dataChunk);
@property (strong) BOOL(^shouldCancelBlock)();

@property (strong) NSObject *threadLock;

Expand Down Expand Up @@ -545,26 +543,24 @@ - (BOOL)extractFilesTo:(NSString *)filePath
return;
}

RARSetCallback(welf.rarFile, AllowCancellationCallbackProc, (long)(__bridge void *) self);
self.shouldCancelBlock = ^BOOL{
BOOL (^shouldCancelBlock)() = ^BOOL {
URKCreateActivity("shouldCancelBlock");
URKLogDebug("Progress.isCancelled: %{public}@", progress.isCancelled ? @"YES" : @"NO")
return progress.isCancelled;
};
RARSetCallback(welf.rarFile, AllowCancellationCallbackProc, (long)shouldCancelBlock);

if ((PFCode = RARProcessFile(welf.rarFile, RAR_EXTRACT, cFilePath, NULL)) != 0) {
RARSetCallback(welf.rarFile, NULL, NULL);
self.shouldCancelBlock = nil;

NSString *errorName = nil;

NSInteger errorCode = progress.isCancelled ? URKErrorCodeUserCancelled : PFCode;
[self assignError:innerError code:errorCode errorName:&errorName];
URKLogError("Error extracting file: %{public}@ (%ld)", errorName, (long)errorCode);
result = NO;
return;
}

[progress setUserInfoObject:@(++filesExtracted)
forKey:NSProgressFileCompletedCountKey];
[progress setUserInfoObject:@(fileInfos.count)
Expand All @@ -586,7 +582,6 @@ - (BOOL)extractFilesTo:(NSString *)filePath
}

RARSetCallback(welf.rarFile, NULL, NULL);
self.shouldCancelBlock = nil;

if (RHCode != ERAR_SUCCESS && RHCode != ERAR_END_ARCHIVE) {
NSString *errorName = nil;
Expand Down Expand Up @@ -693,8 +688,7 @@ - (NSData *)extractDataFromFile:(NSString *)filePath
progressBlock(0.0);
}

RARSetCallback(welf.rarFile, BufferedReadCallbackProc, (long)(__bridge void *) self);
self.bufferedReadBlock = ^BOOL(NSData *dataChunk) {
BOOL (^bufferedReadBlock)(NSData*) = ^BOOL(NSData *dataChunk) {
URKLogDebug("Appending buffered data (%lu bytes)", (unsigned long)dataChunk.length);
[fileData appendData:dataChunk];
progress.completedUnitCount += dataChunk.length;
Expand All @@ -712,12 +706,12 @@ - (NSData *)extractDataFromFile:(NSString *)filePath

return YES;
};

RARSetCallback(welf.rarFile, BufferedReadCallbackProc, (long)bufferedReadBlock);

URKLogInfo("Processing file...");
PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL);

RARSetCallback(welf.rarFile, NULL, NULL);
self.bufferedReadBlock = nil;

if (progress.isCancelled) {
NSString *errorName = nil;
Expand Down Expand Up @@ -948,8 +942,7 @@ - (BOOL)extractBufferedDataFromFile:(NSString *)filePath
// Repeating the argument instead of using positional specifiers, because they don't work with the {} formatters
URKLogDebug("Uncompressed size: %{iec-bytes}lld (%lld bytes) in file", totalBytes, totalBytes);

RARSetCallback(welf.rarFile, BufferedReadCallbackProc, (long)(__bridge void *) self);
self.bufferedReadBlock = ^BOOL(NSData *dataChunk) {
BOOL (^bufferedReadBlock)(NSData*) = ^BOOL(NSData *dataChunk) {
if (progress.isCancelled) {
URKLogInfo("Buffered data read cancelled");
return NO;
Expand All @@ -963,12 +956,12 @@ - (BOOL)extractBufferedDataFromFile:(NSString *)filePath
action(dataChunk, progressPercent);
return YES;
};
RARSetCallback(welf.rarFile, BufferedReadCallbackProc, (long)bufferedReadBlock);

URKLogDebug("Processing file...");
PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL);

RARSetCallback(welf.rarFile, NULL, NULL);
self.bufferedReadBlock = nil;

if (progress.isCancelled) {
NSString *errorName = nil;
Expand Down Expand Up @@ -1166,14 +1159,17 @@ int CALLBACK CallbackProc(UINT msg, long UserData, long P1, long P2) {

int CALLBACK BufferedReadCallbackProc(UINT msg, long UserData, long P1, long P2) {
URKCreateActivity("BufferedReadCallbackProc");
URKArchive *refToSelf = (__bridge URKArchive *)(void *)UserData;
BOOL (^bufferedReadBlock)(NSData*) = (__bridge BOOL(^)(NSData*))(void *)UserData;

if (msg == UCM_PROCESSDATA) {
URKLogDebug("msg: UCM_PROCESSDATA; Copying data chunk and calling read block");
NSData *dataChunk = [NSData dataWithBytesNoCopy:(UInt8 *)P1 length:P2 freeWhenDone:NO];
BOOL cancelRequested = !refToSelf.bufferedReadBlock(dataChunk);
if (cancelRequested) {
return -1;
@autoreleasepool {
URKLogDebug("msg: UCM_PROCESSDATA; Copying data chunk and calling read block");
NSData *dataChunk = [NSData dataWithBytes:(UInt8 *)P1 length:P2];
BOOL cancelRequested = !bufferedReadBlock(dataChunk);

if (cancelRequested) {
return -1;
}
}
}

Expand All @@ -1182,16 +1178,15 @@ int CALLBACK BufferedReadCallbackProc(UINT msg, long UserData, long P1, long P2)

int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, long P2) {
URKCreateActivity("AllowCancellationCallbackProc");
URKArchive *refToSelf = (__bridge URKArchive *)(void *)UserData;
BOOL (^shouldCancelBlock)() = (__bridge BOOL(^)())(void *)UserData;

if (![refToSelf shouldCancelBlock]) {
if (!shouldCancelBlock) {
return 0;
}

BOOL shouldCancel = refToSelf.shouldCancelBlock();
BOOL shouldCancel = shouldCancelBlock();
if (shouldCancel) {
URKLogDebug("Operation cancelled in shouldCancelBlock()");
refToSelf.shouldCancelBlock = nil;
}

return shouldCancel ? -1 : 0;
Expand Down

0 comments on commit d6481c5

Please sign in to comment.