Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 177d6881d88dfc4e1306156c513b7e9c81d41710
      
https://github.com/WebKit/WebKit/commit/177d6881d88dfc4e1306156c513b7e9c81d41710
  Author: Chris Dumez <[email protected]>
  Date:   2023-08-04 (Fri, 04 Aug 2023)

  Changed paths:
    M Source/WTF/wtf/ThreadSafeWeakHashSet.h
    M Source/WTF/wtf/WeakHashMap.h
    M Source/WTF/wtf/WeakHashSet.h
    M Source/WTF/wtf/WeakListHashSet.h
    M Source/WebKit/NetworkProcess/NetworkDataTask.cpp
    M Source/WebKit/NetworkProcess/NetworkDataTaskBlob.cpp
    M Source/WebKit/NetworkProcess/NetworkDataTaskDataURL.cpp
    M Source/WebKit/NetworkProcess/NetworkSession.cpp
    M Source/WebKit/NetworkProcess/NetworkSession.h
    M Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm
    M Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp
    M Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
    M Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp

  Log Message:
  -----------
  Regression: NetworkDataTask's ThreadSafeWeakPtrControlBlock are leaking
https://bugs.webkit.org/show_bug.cgi?id=259808
rdar://112162921

Reviewed by Alex Christensen.

The NetworkProcess memory was growing unboundedly during long-running browsing
benchmarks, which the number of NetworkDataTask's ThreadSafeWeakPtrControlBlock
objects growing very large.

The issue was with the `ThreadSafeWeakHashSet<NetworkDataTask> m_dataTaskSet`
container on the NetworkSession. We would add NetworkDataTask objects to this
WeakHashSet and never explicitly remove them. We had a comment in the code
indicating that the ThreadSafeWeakHashSet's amortized clean up would take care
of removing them. The issue though is that amortized clean up would never happen
and m_dataTaskSet's internal Set would just grow unboundedly, keeping control
blocks alive.

The reason amortized clean up never triggered is that we only add to 
m_dataTaskSet,
we never remove from it, never clear it and we only very rarely call forEach() 
on
it. As a result, ThreadSafeWeakHashSet::m_operationCountSinceLastCleanup would 
only
increment due to the add() calls. The condition for amortized clean up was:
`++m_operationCountSinceLastCleanup / 2 > m_set.size()`.

Since m_operationCountSinceLastCleanup would only increase due to the add() 
calls
and since nothing would ever get removed from the set, 
`m_operationCountSinceLastCleanup / 2`
could never reach the size of the set.

I am making several fixes in this patch:
1. I added a `|| m_operationCountSinceLastCleanup > 
m_maxOperationCountWithoutCleanup`
   check to amortized clean up to guarantee that amortized clean up eventually 
happens
   and that such weak containers can never grow unboundedly, no matter how they 
are used.
   m_maxOperationCountWithoutCleanup gets multiplied by 2 whenever the clean up 
finds
   nothing for proper amortization.
2. I made it so that NetworkDataTask objects remove themselves from the 
ThreadSafeWeakHashSet
   in their destructor. This is good practice no matter what and makes such the 
set stays
   small.
3. I actually found a bug in `ThreadSafeWeakHashSet::remove()` when 
implementing the fix in
   (2). ThreadSafeWeakHashSet::remove() would fail to remove the object from 
the set if the
   call if made after the object destructor has started running! The reason for 
this is that
   the ThreadSafeWeakHashSet was using a `std::pair<ControlBlockRefPtr, const 
T*>` as set
   key internally. This means that we needed to create a ControlBlockRefPtr of 
the object's
   control block in remove() in order to remove the object from the map. 
However, 265344@main
   made it so that ref'ing a control block returns nullptr after the object has 
started
   destruction. As a result, the first item in the key pair would be nullptr 
and we'd fail
   to remove. To address the issue, I am dropping the ControlBlockRefPtr from 
the key and
   using a `HashMap<const T*, ControlBlockRefPtr>` instead of a HashSet.

* Source/WTF/wtf/ThreadSafeWeakHashSet.h:
* Source/WTF/wtf/WeakHashMap.h:
* Source/WTF/wtf/WeakHashSet.h:
* Source/WTF/wtf/WeakListHashSet.h:
* Source/WebKit/NetworkProcess/NetworkDataTask.cpp:
(WebKit::NetworkDataTask::~NetworkDataTask):
* Source/WebKit/NetworkProcess/NetworkSession.cpp:
(WebKit::NetworkSession::registerNetworkDataTask):
(WebKit::NetworkSession::unregisterNetworkDataTask):
* Source/WebKit/NetworkProcess/NetworkSession.h:
* Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp:
(TestWebKitAPI::ObjectAddingAndRemovingItself::create):
(TestWebKitAPI::ObjectAddingAndRemovingItself::~ObjectAddingAndRemovingItself):
(TestWebKitAPI::ObjectAddingAndRemovingItself::ObjectAddingAndRemovingItself):
(TestWebKitAPI::TEST):
(TestWebKitAPI::ObjectAddingItselfOnly::create):
(TestWebKitAPI::ObjectAddingItselfOnly::ObjectAddingItselfOnly):

Canonical link: https://commits.webkit.org/266594@main


_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to