Title: [137783] trunk/Source/WebKit2
Revision
137783
Author
a...@apple.com
Date
2012-12-14 15:33:45 -0800 (Fri, 14 Dec 2012)

Log Message

        <rdar://problem/12874760> NetworkProcess loads may get stuck when WebProcess quits
        https://bugs.webkit.org/show_bug.cgi?id=105056

        Reviewed by Anders Carlsson.

        Make response maps per-connection.

        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
        (WebKit::NetworkConnectionToWebProcess::didClose): Cancel waiting for responses
        from WebProcess, they will never arrive.

        * NetworkProcess/NetworkConnectionToWebProcess.h:
        (WebKit::NetworkConnectionToWebProcess::willSendRequestResponseMap):
        (WebKit::NetworkConnectionToWebProcess::canAuthenticateAgainstProtectionSpaceResponseMap):
        Maps now live here.

        * NetworkProcess/NetworkResourceLoader.cpp:
        (WebKit::NetworkResourceLoader::connectionToWebProcessDidClose): Added a FIXME.

        (WebKit::NetworkResourceLoader::willSendRequest):
        (WebKit::NetworkResourceLoader::willSendRequestHandled):
        (WebKit::NetworkResourceLoader::canAuthenticateAgainstProtectionSpace):
        (WebKit::NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceHandled):
        Handle the cases where we can't send a request, or can't expect a response any more.

        * Shared/BlockingResponseMap.h:
        (BlockingResponseMap):
        (BlockingResponseMap::BlockingResponseMap):
        (BlockingResponseMap::~BlockingResponseMap):
        (BlockingResponseMap::waitForResponse):
        (BlockingResponseMap::didReceiveResponse):
        (BlockingResponseMap::cancel):
        (BlockingBoolResponseMap):
        (BlockingBoolResponseMap::BlockingBoolResponseMap):
        (BlockingBoolResponseMap::~BlockingBoolResponseMap):
        (BlockingBoolResponseMap::waitForResponse):
        (BlockingBoolResponseMap::didReceiveResponse):
        (BlockingBoolResponseMap::cancel):
        Added an ability to cancel, and slightly beefed up overall.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (137782 => 137783)


--- trunk/Source/WebKit2/ChangeLog	2012-12-14 23:23:25 UTC (rev 137782)
+++ trunk/Source/WebKit2/ChangeLog	2012-12-14 23:33:45 UTC (rev 137783)
@@ -1,3 +1,45 @@
+2012-12-14  Alexey Proskuryakov  <a...@apple.com>
+
+        <rdar://problem/12874760> NetworkProcess loads may get stuck when WebProcess quits
+        https://bugs.webkit.org/show_bug.cgi?id=105056
+
+        Reviewed by Anders Carlsson.
+
+        Make response maps per-connection.
+
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::didClose): Cancel waiting for responses
+        from WebProcess, they will never arrive.
+
+        * NetworkProcess/NetworkConnectionToWebProcess.h:
+        (WebKit::NetworkConnectionToWebProcess::willSendRequestResponseMap):
+        (WebKit::NetworkConnectionToWebProcess::canAuthenticateAgainstProtectionSpaceResponseMap):
+        Maps now live here.
+
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::connectionToWebProcessDidClose): Added a FIXME.
+
+        (WebKit::NetworkResourceLoader::willSendRequest):
+        (WebKit::NetworkResourceLoader::willSendRequestHandled):
+        (WebKit::NetworkResourceLoader::canAuthenticateAgainstProtectionSpace):
+        (WebKit::NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceHandled):
+        Handle the cases where we can't send a request, or can't expect a response any more.
+
+        * Shared/BlockingResponseMap.h:
+        (BlockingResponseMap):
+        (BlockingResponseMap::BlockingResponseMap):
+        (BlockingResponseMap::~BlockingResponseMap):
+        (BlockingResponseMap::waitForResponse):
+        (BlockingResponseMap::didReceiveResponse):
+        (BlockingResponseMap::cancel):
+        (BlockingBoolResponseMap):
+        (BlockingBoolResponseMap::BlockingBoolResponseMap):
+        (BlockingBoolResponseMap::~BlockingBoolResponseMap):
+        (BlockingBoolResponseMap::waitForResponse):
+        (BlockingBoolResponseMap::didReceiveResponse):
+        (BlockingBoolResponseMap::cancel):
+        Added an ability to cancel, and slightly beefed up overall.
+
 2012-12-14  Anders Carlsson  <ander...@apple.com>
 
         DownloadProxyMap should keep track of outstanding DownloadProxy objects

Modified: trunk/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp (137782 => 137783)


--- trunk/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp	2012-12-14 23:23:25 UTC (rev 137782)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp	2012-12-14 23:33:45 UTC (rev 137783)
@@ -102,10 +102,11 @@
     RefPtr<NetworkConnectionToWebProcess> protector(this);
     
     NetworkProcess::shared().removeNetworkConnectionToWebProcess(this);
-    
-    // FIXME (NetworkProcess): We might consider actively clearing out all requests for this connection.
-    // But that might not be necessary as the observer mechanism used above is much more direct.
 
+    // Unblock waiting threads.
+    m_willSendRequestResponseMap.cancel();
+    m_canAuthenticateAgainstProtectionSpaceResponseMap.cancel();
+
     Vector<NetworkConnectionToWebProcessObserver*> observers;
     copyToVector(m_observers, observers);
     for (size_t i = 0; i < observers.size(); ++i)

Modified: trunk/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h (137782 => 137783)


--- trunk/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h	2012-12-14 23:23:25 UTC (rev 137782)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h	2012-12-14 23:33:45 UTC (rev 137783)
@@ -28,6 +28,7 @@
 
 #if ENABLE(NETWORK_PROCESS)
 
+#include "BlockingResponseMap.h"
 #include "Connection.h"
 #include "NetworkConnectionToWebProcessMessages.h"
 #include <WebCore/ResourceLoadPriority.h>
@@ -61,6 +62,9 @@
 
     bool isSerialLoadingEnabled() const { return m_serialLoadingEnabled; }
 
+    BlockingResponseMap<WebCore::ResourceRequest*>& willSendRequestResponseMap() { return m_willSendRequestResponseMap; }
+    BlockingBoolResponseMap& canAuthenticateAgainstProtectionSpaceResponseMap() { return m_canAuthenticateAgainstProtectionSpaceResponseMap; }
+
 private:
     NetworkConnectionToWebProcess(CoreIPC::Connection::Identifier);
 
@@ -95,7 +99,10 @@
     RefPtr<CoreIPC::Connection> m_connection;
     
     HashSet<NetworkConnectionToWebProcessObserver*> m_observers;
-    
+
+    BlockingResponseMap<WebCore::ResourceRequest*> m_willSendRequestResponseMap;
+    BlockingBoolResponseMap m_canAuthenticateAgainstProtectionSpaceResponseMap;
+
     bool m_serialLoadingEnabled;
 };
 

Modified: trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp (137782 => 137783)


--- trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp	2012-12-14 23:23:25 UTC (rev 137782)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp	2012-12-14 23:33:45 UTC (rev 137783)
@@ -28,7 +28,6 @@
 
 #if ENABLE(NETWORK_PROCESS)
 
-#include "BlockingResponseMap.h"
 #include "DataReference.h"
 #include "Logging.h"
 #include "NetworkConnectionToWebProcess.h"
@@ -144,6 +143,7 @@
 void NetworkResourceLoader::connectionToWebProcessDidClose(NetworkConnectionToWebProcess* connection)
 {
     ASSERT_ARG(connection, connection == m_connection.get());
+    // FIXME (NetworkProcess): Cancel the load. The request may be long-living, so we don't want it to linger around after all clients are gone.
 }
 
 void NetworkResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
@@ -177,12 +177,6 @@
     scheduleStopOnMainThread();
 }
 
-static BlockingResponseMap<ResourceRequest*>& willSendRequestResponseMap()
-{
-    AtomicallyInitializedStatic(BlockingResponseMap<ResourceRequest*>&, responseMap = *new BlockingResponseMap<ResourceRequest*>);
-    return responseMap;
-}
-
 static uint64_t generateWillSendRequestID()
 {
     static int64_t uniqueWillSendRequestID;
@@ -191,22 +185,25 @@
 
 void NetworkResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
 {
-    // We only expect to get the willSendRequest callback from ResourceHandle as the result of a redirect
+    // We only expect to get the willSendRequest callback from ResourceHandle as the result of a redirect.
     ASSERT(!redirectResponse.isNull());
 
     uint64_t requestID = generateWillSendRequestID();
 
-    send(Messages::WebResourceLoader::WillSendRequest(requestID, request, redirectResponse));
-    
-    OwnPtr<ResourceRequest> newRequest = willSendRequestResponseMap().waitForResponse(requestID);
-    request = *newRequest;
+    if (!send(Messages::WebResourceLoader::WillSendRequest(requestID, request, redirectResponse))) {
+        request = ResourceRequest();
+        return;
+    }
 
+    OwnPtr<ResourceRequest> newRequest = m_connection->willSendRequestResponseMap().waitForResponse(requestID);
+    request = newRequest ? *newRequest : ResourceRequest();
+
     RunLoop::main()->dispatch(WTF::bind(&NetworkResourceLoadScheduler::receivedRedirect, &NetworkProcess::shared().networkResourceLoadScheduler(), m_identifier, request.url()));
 }
 
 void NetworkResourceLoader::willSendRequestHandled(uint64_t requestID, const WebCore::ResourceRequest& newRequest)
 {
-    willSendRequestResponseMap().didReceiveResponse(requestID, adoptPtr(new ResourceRequest(newRequest)));
+    m_connection->willSendRequestResponseMap().didReceiveResponse(requestID, adoptPtr(new ResourceRequest(newRequest)));
 }
 
 // FIXME (NetworkProcess): Many of the following ResourceHandleClient methods definitely need implementations. A few will not.
@@ -300,12 +297,6 @@
 }
 
 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
-static BlockingBoolResponseMap& canAuthenticateAgainstProtectionSpaceResponseMap()
-{
-    AtomicallyInitializedStatic(BlockingBoolResponseMap&, responseMap = *new BlockingBoolResponseMap);
-    return responseMap;
-}
-
 static uint64_t generateCanAuthenticateAgainstProtectionSpaceID()
 {
     static int64_t uniqueCanAuthenticateAgainstProtectionSpaceID;
@@ -316,14 +307,15 @@
 {
     uint64_t requestID = generateCanAuthenticateAgainstProtectionSpaceID();
 
-    send(Messages::WebResourceLoader::CanAuthenticateAgainstProtectionSpace(requestID, protectionSpace));
+    if (!send(Messages::WebResourceLoader::CanAuthenticateAgainstProtectionSpace(requestID, protectionSpace)))
+        return false;
 
-    return canAuthenticateAgainstProtectionSpaceResponseMap().waitForResponse(requestID);
+    return m_connection->canAuthenticateAgainstProtectionSpaceResponseMap().waitForResponse(requestID);
 }
 
 void NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceHandled(uint64_t requestID, bool canAuthenticate)
 {
-    canAuthenticateAgainstProtectionSpaceResponseMap().didReceiveResponse(requestID, canAuthenticate);
+    m_connection->canAuthenticateAgainstProtectionSpaceResponseMap().didReceiveResponse(requestID, canAuthenticate);
 }
 #endif
 

Modified: trunk/Source/WebKit2/Shared/BlockingResponseMap.h (137782 => 137783)


--- trunk/Source/WebKit2/Shared/BlockingResponseMap.h	2012-12-14 23:23:25 UTC (rev 137782)
+++ trunk/Source/WebKit2/Shared/BlockingResponseMap.h	2012-12-14 23:33:45 UTC (rev 137783)
@@ -33,12 +33,19 @@
 
 template<typename T>
 class BlockingResponseMap {
+WTF_MAKE_NONCOPYABLE(BlockingResponseMap);
 public:
+    BlockingResponseMap() : m_canceled(false) { }
+    ~BlockingResponseMap() { ASSERT(m_responses.isEmpty()); }
+
     PassOwnPtr<T> waitForResponse(uint64_t requestID)
     {
         while (true) {
             MutexLocker locker(m_mutex);
 
+            if (m_canceled)
+                return nullptr;
+
             if (OwnPtr<T> response = m_responses.take(requestID))
                 return response.release();
 
@@ -54,24 +61,41 @@
         ASSERT(!m_responses.contains(requestID));
 
         m_responses.set(requestID, response);
-        // FIXME (NetworkProcess): Waking up all threads is quite inefficient.
+        // FIXME (NetworkProcess): <rdar://problem/12886430>: Waking up all threads is quite inefficient.
         m_condition.broadcast();
     }
 
+    void cancel()
+    {
+        m_canceled = true;
+
+        // FIXME (NetworkProcess): <rdar://problem/12886430>: Waking up all threads is quite inefficient.
+        m_condition.broadcast();
+    }
+
 private:
     Mutex m_mutex;
     ThreadCondition m_condition;
 
     HashMap<uint64_t, OwnPtr<T> > m_responses;
+    bool m_canceled;
 };
 
 class BlockingBoolResponseMap {
+WTF_MAKE_NONCOPYABLE(BlockingBoolResponseMap);
 public:
+    BlockingBoolResponseMap() : m_canceled(false) { }
+    ~BlockingBoolResponseMap() { ASSERT(m_responses.isEmpty()); }
+
     bool waitForResponse(uint64_t requestID)
     {
         while (true) {
             MutexLocker locker(m_mutex);
 
+            // FIXME: Differentiate between canceled wait and a negative response.
+            if (m_canceled)
+                return false;
+
             HashMap<uint64_t, bool>::iterator iter = m_responses.find(requestID);
             if (iter != m_responses.end()) {
                 bool result = iter->value;
@@ -91,15 +115,24 @@
         ASSERT(!m_responses.contains(requestID));
 
         m_responses.set(requestID, response);
-        // FIXME (NetworkProcess): Waking up all threads is quite inefficient.
+        // FIXME (NetworkProcess): <rdar://problem/12886430>: Waking up all threads is quite inefficient.
         m_condition.broadcast();
     }
 
+    void cancel()
+    {
+        m_canceled = true;
+
+        // FIXME (NetworkProcess): <rdar://problem/12886430>: Waking up all threads is quite inefficient.
+        m_condition.broadcast();
+    }
+
 private:
     Mutex m_mutex;
     ThreadCondition m_condition;
 
     HashMap<uint64_t, bool> m_responses;
+    bool m_canceled;
 };
 
 #endif // BlockingResponseMap_h
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to