Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RLMNetworkClient leaks NSURLSession #6058

Closed
molind opened this issue Jan 8, 2019 · 2 comments · Fixed by #6062
Closed

RLMNetworkClient leaks NSURLSession #6058

molind opened this issue Jan 8, 2019 · 2 comments · Fixed by #6062
Assignees

Comments

@molind
Copy link
Contributor

molind commented Jan 8, 2019

!!! MANDATORY TO FILL OUT !!!

Goals

Receive synchronized realm.

Expected Results

Realm is returned. No leaks happened.

Actual Results

RLMNetworkClient leaks NSURLSessions.

Steps to Reproduce

Every call to [RLMNetworkClient sendRequestToEndpoint] leaks one NSURLSession.

Code Sample

Leaking delegate code:

- (void)URLSession:(__unused NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
    if (error) {
        _completionBlock(error, nil);
        return;
    }

    if (![self validateResponse:task.response data:_data error:&error]) {
        _completionBlock(error, nil);
        return;
    }

    id json = [NSJSONSerialization JSONObjectWithData:_data
                                              options:(NSJSONReadingOptions)0
                                                error:&error];
    if (!json) {
        _completionBlock(error, nil);
        return;
    }
    if (![json isKindOfClass:[NSDictionary class]]) {
        _completionBlock(make_auth_error_bad_response(json), nil);
        return;
    }

    _completionBlock(nil, (NSDictionary *)json);
}

Fixed proof of concept (ugly, but won't leak):

- (void)completeTask:(NSURLSessionTask *)task withError:(NSError *)error {
    if (error) {
        _completionBlock(error, nil);
        return;
    }
    
    if (![self validateResponse:task.response data:_data error:&error]) {
        _completionBlock(error, nil);
        return;
    }
    
    id json = [NSJSONSerialization JSONObjectWithData:_data
                                              options:(NSJSONReadingOptions)0
                                                error:&error];
    if (!json) {
        _completionBlock(error, nil);
        return;
    }
    if (![json isKindOfClass:[NSDictionary class]]) {
        _completionBlock(make_auth_error_bad_response(json), nil);
        return;
    }
    
    _completionBlock(nil, (NSDictionary *)json);
}

- (void)URLSession:(__unused NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
    [self completeTask:task withError:error];
    _completionBlock = nil;
    [session finishTasksAndInvalidate];
}

Whole concept with new NSURLSession per request seems wrong to me. Because each NSURLSession is ready to process multiple tasks. Why won't create one shared instance of NSURLSession per pinnedCertificatePaths?
Then you could put cert validation into NSURLSessionDelegate as you do now. And json parsing error checking into task completionHandler.
Other option is to invalidate session when task is processed as shown above.

screen shot 2019-01-08 at 18 05 47

Version of Realm and Tooling

Realm framework version: 3.10.0

Realm Object Server version: 3.4.3

Xcode version: 10.1

iOS/OSX version: iOS 12.1.2

Dependency manager + version:

@bmunkholm
Copy link
Contributor

Thanks a lot for the detailed issue and even suggested fix!
We will take a closer look at it.

@molind
Copy link
Contributor Author

molind commented Jan 9, 2019

Actual leaking part is here:
https://github.com/realm/realm-cocoa/blob/56afd03af7f205cee74e9fd359c3f5b7fa502d66/Realm/RLMNetworkClient.mm#L421-L427

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants