Skip to content

Memory spike problem and the fix #32

@Samx2015

Description

@Samx2015

When encrypting/decrypting large files, in our case, the memory usage spikes to 1.5G and app quickly crashes. We found the problem to be caused by RNCryptorEngine:addData:error creating 48K NSData objects that are not released fast enough. The fix is pretty simple: to add @autoreleaseblock to the two functions that use RNCryptorEngine:addData:error:

RNEncryptor:

- (void)addData:(NSData *)data
{
    if (self.isFinished) {
        return;
    }
    
    dispatch_async(self.queue, ^{
        @autoreleasepool { // this fixes the memory issue
            if (!self.haveWrittenHeader) {
                NSData *header = [self header];
                [self.outData setData:header];
                if (self.hasHMAC) {
                    CCHmacUpdate(&self->_HMACContext, [header bytes], [header length]);
                }
                self.haveWrittenHeader = YES;
            }
            
            NSError *error = nil;
            NSData *encryptedData = [self.engine addData:data error:&error];
            if (!encryptedData) {
                [self cleanupAndNotifyWithError:error];
            }
            if (self.hasHMAC) {
                CCHmacUpdate(&self->_HMACContext, encryptedData.bytes, encryptedData.length);
            }
            
            [self.outData appendData:encryptedData];
            
            dispatch_sync(self.responseQueue, ^{
                self.handler(self, self.outData);
            });
            [self.outData setLength:0];
        }
    });
}

RNDecryptor:

- (void)decryptData:(NSData *)data
{
    dispatch_async(self.queue, ^{
        @autoreleasepool { // this fixes the memory issue
            if (self.hasHMAC) {
                CCHmacUpdate(&self->_HMACContext, data.bytes, data.length);
            }
            
            NSError *error = nil;
            NSData *decryptedData = [self.engine addData:data error:&error];
            
            if (!decryptedData) {
                [self cleanupAndNotifyWithError:error];
                return;
            }
            
            [self.outData appendData:decryptedData];
            
            dispatch_sync(self.responseQueue, ^{
                self.handler(self, self.outData);
            });
            [self.outData setLength:0];
        }
    });
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions