⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 242693 in webkit


Ignore:
Timestamp:
Mar 10, 2019, 5:27:22 PM (7 years ago)
Author:
david_quesada@apple.com
Message:

ASSERT(m_downloads.isEmpty()) fails in DownloadProxyMap::~DownloadProxyMap()
https://bugs.webkit.org/show_bug.cgi?id=152480

Reviewed by Chris Dumez.

Source/WebKit:

  • UIProcess/Downloads/DownloadProxyMap.cpp:

(WebKit::DownloadProxyMap::downloadFinished):

If the DownloadProxy is holding the last reference to the process pool, then
invalidating the proxy will cause the process pool, the network process proxy,
and this DownloadProxyMap to deallocate. Ensure that doesn't happen until this
method has done everything it wants to do to clean up.

Tools:

Add a unit test based on Daniel Bates's test case that starts a download, ensures
there are no additional references to the process pool besides the one held by
the download, waits for the download to finish (in the sense that the
DownloadProxyMap is done tracking the DownloadProxy), and doesn't crash. For good
measure, also check that the process pool has been deallocated at the end of the
test. The test wouldn't be meaningful if the process pool were still alive.

  • TestWebKitAPI/Tests/WebKitCocoa/Download.mm:

(-[WaitUntilDownloadCanceledDelegate _downloadDidStart:]):
(-[WaitUntilDownloadCanceledDelegate _downloadDidCancel:]):

The download will be canceled because the delegate does not implement the
method to decide the download's destination, so this is where we know the
DownloadProxyMap is done with the DownloadProxy.

(TEST):

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r242690 r242693  
     12019-03-10  David Quesada  <david_quesada@apple.com>
     2
     3        ASSERT(m_downloads.isEmpty()) fails in DownloadProxyMap::~DownloadProxyMap()
     4        https://bugs.webkit.org/show_bug.cgi?id=152480
     5
     6        Reviewed by Chris Dumez.
     7
     8        * UIProcess/Downloads/DownloadProxyMap.cpp:
     9        (WebKit::DownloadProxyMap::downloadFinished):
     10            If the DownloadProxy is holding the last reference to the process pool, then
     11            invalidating the proxy will cause the process pool, the network process proxy,
     12            and this DownloadProxyMap to deallocate. Ensure that doesn't happen until this
     13            method has done everything it wants to do to clean up.
     14
    1152019-03-10  Wenson Hsieh  <wenson_hsieh@apple.com>
    216
  • trunk/Source/WebKit/UIProcess/Downloads/DownloadProxyMap.cpp

    r242662 r242693  
    7272    auto downloadID = downloadProxy->downloadID();
    7373
     74    // The DownloadProxy may be holding the last reference to the process pool.
     75    auto protectedProcessPool = makeRefPtr(m_process->processPool());
     76
    7477    ASSERT(m_downloads.contains(downloadID));
    7578
  • trunk/Tools/ChangeLog

    r242664 r242693  
     12019-03-10  David Quesada  <david_quesada@apple.com>
     2
     3        ASSERT(m_downloads.isEmpty()) fails in DownloadProxyMap::~DownloadProxyMap()
     4        https://bugs.webkit.org/show_bug.cgi?id=152480
     5
     6        Reviewed by Chris Dumez.
     7
     8        Add a unit test based on Daniel Bates's test case that starts a download, ensures
     9        there are no additional references to the process pool besides the one held by
     10        the download, waits for the download to finish (in the sense that the
     11        DownloadProxyMap is done tracking the DownloadProxy), and doesn't crash. For good
     12        measure, also check that the process pool has been deallocated at the end of the
     13        test. The test wouldn't be meaningful if the process pool were still alive.
     14
     15        * TestWebKitAPI/Tests/WebKitCocoa/Download.mm:
     16        (-[WaitUntilDownloadCanceledDelegate _downloadDidStart:]):
     17        (-[WaitUntilDownloadCanceledDelegate _downloadDidCancel:]):
     18            The download will be canceled because the delegate does not implement the
     19            method to decide the download's destination, so this is where we know the
     20            DownloadProxyMap is done with the DownloadProxy.
     21        (TEST):
     22
    1232019-03-08  Chris Dumez  <cdumez@apple.com>
    224
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Download.mm

    r242521 r242693  
    4343#import <wtf/MainThread.h>
    4444#import <wtf/RetainPtr.h>
     45#import <wtf/WeakObjCPtr.h>
    4546#import <wtf/text/WTFString.h>
    4647
     
    736737}
    737738
     739static bool didDownloadStart;
     740
     741@interface WaitUntilDownloadCanceledDelegate : NSObject <_WKDownloadDelegate>
     742@end
     743
     744@implementation WaitUntilDownloadCanceledDelegate
     745
     746- (void)_downloadDidStart:(_WKDownload *)download
     747{
     748    didDownloadStart = true;
     749}
     750
     751- (void)_downloadDidCancel:(_WKDownload *)download
     752{
     753    isDone = true;
     754}
     755
     756@end
     757
     758TEST(_WKDownload, CrashAfterDownloadDidFinishWhenDownloadProxyHoldsTheLastRefOnWebProcessPool)
     759{
     760    auto navigationDelegate = adoptNS([[DownloadNavigationDelegate alloc] init]);
     761    auto downloadDelegate = adoptNS([[WaitUntilDownloadCanceledDelegate alloc] init]);
     762    WeakObjCPtr<WKProcessPool> processPool;
     763    @autoreleasepool {
     764        RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
     765        [webView setNavigationDelegate:navigationDelegate.get()];
     766        processPool = [webView configuration].processPool;
     767        [webView configuration].processPool._downloadDelegate = downloadDelegate.get();
     768        [webView loadRequest:[NSURLRequest requestWithURL:sourceURL]];
     769
     770        didDownloadStart = false;
     771        TestWebKitAPI::Util::run(&didDownloadStart);
     772    }
     773
     774    isDone = false;
     775    TestWebKitAPI::Util::run(&isDone);
     776    EXPECT_NULL(processPool.get());
     777}
     778
    738779#endif
Note: See TracChangeset for help on using the changeset viewer.