NSOperationQueue and NSOperation memory leak

Hi,


I'm developing an uploader of with NSOperations. I got it to work with NSURLSessionConfiguration using background config, but it is buggy beacuse some of the memory leak that I'm experiencing with NSOperation.


my code is kind of big to post it here but If you want I can do that. I'll try to explain overall what I'm doing.


I have a UploadOperation that depends on a ConvertFile Operation. I have a NSOperationQueue configure like this:


self.uploadQueue = [NSOperationQueue new];

self.uploadQueue.name = @"Upload Process Queue";

self.uploadQueue.maxConcurrentOperationCount = 4;

self.uploadQueue.qualityOfService = NSOperationQualityOfServiceUserInitiated;


The upload only starts after the file is successfuly converted... OK...

Now the uploadOperation kicks in.. it reads to a NSData like so NSData* data = [[NSData alloc] initWithContentsOfFile:self.pathFile];
and the I create the request ... and add it to the background NSURLSessionUploadTask and the even clear the nsdata, the request and the body from the main() of the upload uperation.. but this does not change a thing.

...

[request setHTTPBody:body];

self.uploadDataTask = [self.sessionURLBackground uploadTaskWithStreamedRequest:request];

[self.uploadDataTask resume];

data = nil;

request = nil;

body = nil;


At this time the memory jumps because the files are Images and Movies... and each time a Upload operation kicks in the memory only grows. the Operation finishes and the memory isn't released... which leads, some times to the bug... It fails on URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error with an error of Error Domain=NSURLErrorDomain Code=-997 Lost connection to background transfer service...


This only happens sometimes when I add like 3 or 4 videos and the memory gets over 60 MB... and if one upload operation fails I create a new NSOperation to upload the same file and the memory still only rises... never decreases...


Is there a trick to force clear all finished NSOperations?

Answered by rickrvo in 85173022

I had to change the PHP side to accept this kind of request created with uploadTaskWithRequest:request fromFile and it works fine! And withou any memory leak! 🙂


Thanks

You could try adding an @autoreleasepool { } block to contain the bits of code that are generating a lot of temporary objects. When doing stuff in background threads, the pool doesn't always get drained automatically every pass through the run loop like it does with the main thread. (Well it does in certain cases but depending on how you're implementing your operation class, it might not.)


What does Instruments say? Are there numbers of any particular object increasing steadily? If so, who is holding those references?

Hi junkpile! thanks for the enlightment. I didn't use Instruments before. I was able to se that it was NSURLSession that was leaking memory and not the NSOperations. Well I think that is the backgroundSession that has the memory leak but I still couldn't test it properly...


I'm using a backgroundSessionConfiguration and was reading the file to a NSData, creating the request manually and sending the data using:

self.uploadDataTask = [self.sessionURLBackground uploadTaskWithStreamedRequest:request];


I remember that it was the only way I made it to work. Now I'm trying to use:

self.uploadDataTask = [self.sessionURLBackground uploadTaskWithRequest:request fromFile:[[NSURL alloc] initFileURLWithPath:self.pathFile]];


This should be the correct way and maybe get rid of the memory leaking problem... BUT... now I cant get my uploads to work... even if I set:

[request addValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"];


When I debug the request it ignores my Content-Type and it send this POST request to the PHP server:

{

args = {

};

data = "data:application/octet-stream;base64,/9j/4AAQSkZJRgABAQAASABIAA ...";

files = {

};

form = {

};

headers = {

Accept = "*/";

"Accept-Encoding" = "gzip, deflate";

"Accept-Language" = "pt-br";

Appagent = iOS;

"Content-Length" = 510900;

"Content-Type" = "image/jpeg";

Host = "httpbin.org";

Idsession = "xxx";

"User-Agent" = "SFTest/1 CFNetwork/758.1.6 Darwin/15.0.0";

};

json = "<null>";

origin = "xxx.xxx.xxx.xxx";

url = "http:/

}


It ignores my Content-Type and sends in the "data" field as application/octet-stream instead of "files" field... and the PHP says that $_FILES is empty...


😢

Accepted Answer

I had to change the PHP side to accept this kind of request created with uploadTaskWithRequest:request fromFile and it works fine! And withou any memory leak! 🙂


Thanks

NSOperationQueue and NSOperation memory leak
 
 
Q