Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(558)

Unified Diff: Source/core/fetch/Resource.cpp

Issue 231873006: Make sure resource client is called asynchronously (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: stupid cq won't let me land Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/fetch/RawResourceTest.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/fetch/Resource.cpp
diff --git a/Source/core/fetch/Resource.cpp b/Source/core/fetch/Resource.cpp
index 936193b9f27e34bf19c43464216663076a2e5162..78945ed00200717585fa7e8f470ed9e9fe6994b4 100644
--- a/Source/core/fetch/Resource.cpp
+++ b/Source/core/fetch/Resource.cpp
@@ -478,7 +478,7 @@ void Resource::removeClient(ResourceClient* client)
if (m_clientsAwaitingCallback.isEmpty())
ResourceCallback::callbackHandler()->cancel(this);
} else {
- ASSERT(m_clients.contains(client));
+ RELEASE_ASSERT(m_clients.contains(client));
m_clients.remove(client);
didRemoveClient(client);
}
@@ -563,12 +563,35 @@ void Resource::didAccessDecodedData()
void Resource::finishPendingClients()
{
- while (!m_clientsAwaitingCallback.isEmpty()) {
- ResourceClient* client = m_clientsAwaitingCallback.begin()->key;
- m_clientsAwaitingCallback.remove(client);
+ // We're going to notify clients one by one. It is simple if the client does nothing.
+ // However there are a couple other things that can happen.
+ //
+ // 1. Clients can be added during the loop. Make sure they are not processed.
+ // 2. Clients can be removed during the loop. Make sure they are always available to be
+ // removed. Also don't call removed clients or add them back.
+
+ // Handle case (1) by saving a list of clients to notify. A separate list also ensure
+ // a client is either in m_clients or m_clientsAwaitingCallback.
+ Vector<ResourceClient*> clientsToNotify;
+ copyToVector(m_clientsAwaitingCallback, clientsToNotify);
+
+ for (size_t i = 0; i < clientsToNotify.size(); ++i) {
+ ResourceClient* client = clientsToNotify[i];
+
+ // Handle case (2) to skip removed clients.
+ if (!m_clientsAwaitingCallback.remove(client))
+ continue;
m_clients.add(client);
didAddClient(client);
}
+
+ bool scheduled = ResourceCallback::callbackHandler()->isScheduled(this);
+ // It is a critical problem if a callback is scheduled but there is no client waiting for it.
+ // Such a callback cannot be cancelled. It is better to crash the renderer now.
+ RELEASE_ASSERT(!scheduled || !m_clientsAwaitingCallback.isEmpty());
+
+ // Prevent the case when there are clients waiting but no callback scheduled.
+ ASSERT(m_clientsAwaitingCallback.isEmpty() || scheduled);
}
void Resource::prune()
« no previous file with comments | « Source/core/fetch/RawResourceTest.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698