Changeset 212198 in webkit


Ignore:
Timestamp:
Feb 11, 2017 8:10:20 PM (7 years ago)
Author:
achristensen@apple.com
Message:

Fix crashes after [NSURLSession invalidateAndCancel]
https://bugs.webkit.org/show_bug.cgi?id=168181
<rdar://problem/29813868>

Reviewed by Brady Eidson.

When we call NetworkSessionCocoa::invalidateAndCancel, we intend for the session to immediately
become invalid and stop doing things. [NSURLSession invalidateAndCancel] asynchronously cancels
everything and then calls the delegate's didBecomeInvalidWithError, so before this change there
is a time when we have torn down the session with SessionTracker::destroySession but we can still
get a delegate callback which assumes the session and its NetworkStorageSession exists. If we
get any delegate callbacks after a NetworkSession has been invalidated, we will want to ignore them.

  • NetworkProcess/cocoa/NetworkSessionCocoa.mm:

(-[WKNetworkSessionDelegate sessionInvalidated]):
(-[WKNetworkSessionDelegate URLSession:didBecomeInvalidWithError:]):
(-[WKNetworkSessionDelegate URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:]):
(-[WKNetworkSessionDelegate URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:]):
(-[WKNetworkSessionDelegate URLSession:task:_schemeUpgraded:completionHandler:]):
(-[WKNetworkSessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
(-[WKNetworkSessionDelegate URLSession:task:didCompleteWithError:]):
(-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveResponse:completionHandler:]):
(-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveData:]):
(-[WKNetworkSessionDelegate URLSession:downloadTask:didFinishDownloadingToURL:]):
(-[WKNetworkSessionDelegate URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:]):
(-[WKNetworkSessionDelegate URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:]):
(-[WKNetworkSessionDelegate URLSession:dataTask:didBecomeDownloadTask:]):
The pointer to the NetworkSessionCocoa can now be null. We need to check it.
(WebKit::NetworkSessionCocoa::invalidateAndCancel):
Synchronously remove the connection between the delegates and the NetworkSessionCocoa.

Location:
trunk/Source/WebKit2
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r212183 r212198  
     12017-02-11  Alex Christensen  <achristensen@webkit.org>
     2
     3        Fix crashes after [NSURLSession invalidateAndCancel]
     4        https://bugs.webkit.org/show_bug.cgi?id=168181
     5        <rdar://problem/29813868>
     6
     7        Reviewed by Brady Eidson.
     8
     9        When we call NetworkSessionCocoa::invalidateAndCancel, we intend for the session to immediately
     10        become invalid and stop doing things. [NSURLSession invalidateAndCancel] asynchronously cancels
     11        everything and then calls the delegate's didBecomeInvalidWithError, so before this change there
     12        is a time when we have torn down the session with SessionTracker::destroySession but we can still
     13        get a delegate callback which assumes the session and its NetworkStorageSession exists.  If we
     14        get any delegate callbacks after a NetworkSession has been invalidated, we will want to ignore them.
     15
     16        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
     17        (-[WKNetworkSessionDelegate sessionInvalidated]):
     18        (-[WKNetworkSessionDelegate URLSession:didBecomeInvalidWithError:]):
     19        (-[WKNetworkSessionDelegate URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:]):
     20        (-[WKNetworkSessionDelegate URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:]):
     21        (-[WKNetworkSessionDelegate URLSession:task:_schemeUpgraded:completionHandler:]):
     22        (-[WKNetworkSessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
     23        (-[WKNetworkSessionDelegate URLSession:task:didCompleteWithError:]):
     24        (-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveResponse:completionHandler:]):
     25        (-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveData:]):
     26        (-[WKNetworkSessionDelegate URLSession:downloadTask:didFinishDownloadingToURL:]):
     27        (-[WKNetworkSessionDelegate URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:]):
     28        (-[WKNetworkSessionDelegate URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:]):
     29        (-[WKNetworkSessionDelegate URLSession:dataTask:didBecomeDownloadTask:]):
     30        The pointer to the NetworkSessionCocoa can now be null. We need to check it.
     31        (WebKit::NetworkSessionCocoa::invalidateAndCancel):
     32        Synchronously remove the connection between the delegates and the NetworkSessionCocoa.
     33
    1342017-02-10  John Wilander  <wilander@apple.com>
    235
  • trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm

    r211751 r212198  
    8888
    8989- (id)initWithNetworkSession:(WebKit::NetworkSessionCocoa&)session withCredentials:(bool)withCredentials;
     90- (void)sessionInvalidated;
    9091
    9192@end
     
    105106}
    106107
     108- (void)sessionInvalidated
     109{
     110    _session = nullptr;
     111}
     112
    107113- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error
    108114{
    109     _session = nullptr;
     115    ASSERT(!_session);
    110116}
    111117
    112118- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
    113119{
     120    if (!_session)
     121        return;
     122
    114123    auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
    115124    if (auto* networkDataTask = _session->dataTaskForIdentifier(task.taskIdentifier, storedCredentials))
     
    119128- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler
    120129{
     130    if (!_session) {
     131        completionHandler(nil);
     132        return;
     133    }
     134
    121135    auto taskIdentifier = task.taskIdentifier;
    122136    LOG(NetworkSession, "%llu willPerformHTTPRedirection from %s to %s", taskIdentifier, response.URL.absoluteString.UTF8String, request.URL.absoluteString.UTF8String);
     
    138152- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask*)task _schemeUpgraded:(NSURLRequest*)request completionHandler:(void (^)(NSURLRequest*))completionHandler
    139153{
     154    if (!_session) {
     155        completionHandler(nil);
     156        return;
     157    }
     158
    140159    auto taskIdentifier = task.taskIdentifier;
    141160    LOG(NetworkSession, "%llu _schemeUpgraded %s", taskIdentifier, request.URL.absoluteString.UTF8String);
     
    157176- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler
    158177{
     178    if (!_session) {
     179        completionHandler(nil);
     180        return;
     181    }
     182
    159183    // FIXME: remove if <rdar://problem/20001985> is ever resolved.
    160184    if ([proposedResponse.response respondsToSelector:@selector(allHeaderFields)]
     
    167191- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
    168192{
     193    if (!_session) {
     194        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
     195        return;
     196    }
     197
    169198    auto taskIdentifier = task.taskIdentifier;
    170199    LOG(NetworkSession, "%llu didReceiveChallenge", taskIdentifier);
     
    208237- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    209238{
     239    if (!_session)
     240        return;
     241
    210242    LOG(NetworkSession, "%llu didCompleteWithError %@", task.taskIdentifier, error);
    211243    auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
     
    233265- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
    234266{
     267    if (!_session) {
     268        completionHandler(NSURLSessionResponseCancel);
     269        return;
     270    }
     271
    235272    auto taskIdentifier = dataTask.taskIdentifier;
    236273    LOG(NetworkSession, "%llu didReceiveResponse", taskIdentifier);
     
    266303- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
    267304{
     305    if (!_session)
     306        return;
     307
    268308    auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
    269309    if (auto* networkDataTask = _session->dataTaskForIdentifier(dataTask.taskIdentifier, storedCredentials))
     
    273313- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    274314{
     315    if (!_session)
     316        return;
     317
    275318    auto downloadID = _session->takeDownloadID([downloadTask taskIdentifier]);
    276319    if (auto* download = WebKit::NetworkProcess::singleton().downloadManager().download(downloadID))
     
    280323- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    281324{
     325    if (!_session)
     326        return;
     327
    282328    auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
    283329    ASSERT_WITH_MESSAGE_UNUSED(storedCredentials, !_session->dataTaskForIdentifier([downloadTask taskIdentifier], storedCredentials), "The NetworkDataTask should be destroyed immediately after didBecomeDownloadTask returns");
     
    290336- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
    291337{
     338    if (!_session)
     339        return;
     340
    292341    notImplemented();
    293342}
     
    295344- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
    296345{
     346    if (!_session)
     347        return;
     348
    297349    auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
    298350    if (auto* networkDataTask = _session->dataTaskForIdentifier([dataTask taskIdentifier], storedCredentials)) {
     
    470522    [m_sessionWithCredentialStorage invalidateAndCancel];
    471523    [m_sessionWithoutCredentialStorage invalidateAndCancel];
    472 }
    473 
     524    [m_sessionWithCredentialStorageDelegate sessionInvalidated];
     525    [m_sessionWithoutCredentialStorageDelegate sessionInvalidated];
     526}
    474527
    475528void NetworkSessionCocoa::clearCredentials()
Note: See TracChangeset for help on using the changeset viewer.