Title: [169389] trunk/Source/WebKit2
Revision
169389
Author
barraclo...@apple.com
Date
2014-05-27 10:36:55 -0700 (Tue, 27 May 2014)

Log Message

Add UI process watchdog on iOS to ensure WebProcess connections close
https://bugs.webkit.org/show_bug.cgi?id=133200
<rdar://problem/16997983>

Reviewed by Darin Adler.

When the WebProcessProxy wants to disconnect from a WebContent process it just drops the connection,
and hopes the connection closes. There is a watchdog thread in the ChildProcess to try to ensure this
happens.

On iOS the process may not be runnable at the time, preventing termination. Instead add a watchdog in
the UI process to make the process runnable, and to terminate if it doesn't quit in a timely fashion.

* Platform/IPC/Connection.h:
    - added terminateSoon.
* Platform/IPC/mac/ConnectionMac.mm:
(IPC::ConnectionTerminationWatchdog::ConnectionTerminationWatchdog):
    - take an assertion to make the process runnable, and start a watchdog timer.
(IPC::ConnectionTerminationWatchdog::watchdogTimerFired):
    - if the process hasn't quit by the timer the watchdog fires, kill it.
(IPC::Connection::terminateSoon):
    - create a ConnectionTerminationWatchdog.
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::removeWebPage):
    - when disconnecting from a process, first tell it to terminateSoon.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (169388 => 169389)


--- trunk/Source/WebKit2/ChangeLog	2014-05-27 17:36:21 UTC (rev 169388)
+++ trunk/Source/WebKit2/ChangeLog	2014-05-27 17:36:55 UTC (rev 169389)
@@ -1,3 +1,31 @@
+2014-05-27  Gavin Barraclough  <baraclo...@apple.com>
+
+        Add UI process watchdog on iOS to ensure WebProcess connections close
+        https://bugs.webkit.org/show_bug.cgi?id=133200
+        <rdar://problem/16997983>
+
+        Reviewed by Darin Adler.
+
+        When the WebProcessProxy wants to disconnect from a WebContent process it just drops the connection,
+        and hopes the connection closes. There is a watchdog thread in the ChildProcess to try to ensure this
+        happens.
+
+        On iOS the process may not be runnable at the time, preventing termination. Instead add a watchdog in
+        the UI process to make the process runnable, and to terminate if it doesn't quit in a timely fashion.
+
+        * Platform/IPC/Connection.h:
+            - added terminateSoon.
+        * Platform/IPC/mac/ConnectionMac.mm:
+        (IPC::ConnectionTerminationWatchdog::ConnectionTerminationWatchdog):
+            - take an assertion to make the process runnable, and start a watchdog timer.
+        (IPC::ConnectionTerminationWatchdog::watchdogTimerFired):
+            - if the process hasn't quit by the timer the watchdog fires, kill it.
+        (IPC::Connection::terminateSoon):
+            - create a ConnectionTerminationWatchdog.
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::removeWebPage):
+            - when disconnecting from a process, first tell it to terminateSoon.
+
 2014-05-26  Gavin Barraclough  <barraclo...@apple.com>
 
         importance_assertion -> denap_assertion

Modified: trunk/Source/WebKit2/Platform/IPC/Connection.h (169388 => 169389)


--- trunk/Source/WebKit2/Platform/IPC/Connection.h	2014-05-27 17:36:21 UTC (rev 169388)
+++ trunk/Source/WebKit2/Platform/IPC/Connection.h	2014-05-27 17:36:55 UTC (rev 169389)
@@ -183,6 +183,7 @@
 
 #if PLATFORM(COCOA)
     bool kill();
+    void terminateSoon(double intervalInSeconds);
 #endif
 
 private:

Modified: trunk/Source/WebKit2/Platform/IPC/mac/ConnectionMac.mm (169388 => 169389)


--- trunk/Source/WebKit2/Platform/IPC/mac/ConnectionMac.mm	2014-05-27 17:36:21 UTC (rev 169388)
+++ trunk/Source/WebKit2/Platform/IPC/mac/ConnectionMac.mm	2014-05-27 17:36:55 UTC (rev 169389)
@@ -36,6 +36,10 @@
 #include <wtf/RunLoop.h>
 #include <xpc/xpc.h>
 
+#if PLATFORM(IOS)
+#include "ProcessAssertion.h"
+#endif
+
 #if __has_include(<xpc/private.h>)
 #include <xpc/private.h>
 #else
@@ -65,6 +69,41 @@
     MessageBodyIsOutOfLine = 1 << 0
 };
     
+// ConnectionTerminationWatchdog does two things:
+// 1) It sets a watchdog timer to kill the peered process.
+// 2) On iOS, make the process runnable for the duration of the watchdog
+//    to ensure it has a chance to terminate cleanly.
+class ConnectionTerminationWatchdog {
+public:
+    static void createConnectionTerminationWatchdog(XPCPtr<xpc_connection_t>& xpcConnection, double intervalInSeconds)
+    {
+        new ConnectionTerminationWatchdog(xpcConnection, intervalInSeconds);
+    }
+    
+private:
+    ConnectionTerminationWatchdog(XPCPtr<xpc_connection_t>& xpcConnection, double intervalInSeconds)
+        : m_xpcConnection(xpcConnection)
+        , m_watchdogTimer(RunLoop::main(), this, &ConnectionTerminationWatchdog::watchdogTimerFired)
+#if PLATFORM(IOS)
+        , m_assertion(std::make_unique<WebKit::ProcessAssertion>(xpc_connection_get_pid(m_xpcConnection.get()), WebKit::AssertionState::Background))
+#endif
+    {
+        m_watchdogTimer.startOneShot(intervalInSeconds);
+    }
+    
+    void watchdogTimerFired()
+    {
+        xpc_connection_kill(m_xpcConnection.get(), SIGKILL);
+        delete this;
+    }
+
+    XPCPtr<xpc_connection_t> m_xpcConnection;
+    RunLoop::Timer<ConnectionTerminationWatchdog> m_watchdogTimer;
+#if PLATFORM(IOS)
+    std::unique_ptr<WebKit::ProcessAssertion> m_assertion;
+#endif
+};
+    
 void Connection::platformInvalidate()
 {
     if (!m_isConnected)
@@ -97,7 +136,13 @@
 
     m_xpcConnection = nullptr;
 }
-
+    
+void Connection::terminateSoon(double intervalInSeconds)
+{
+    if (m_xpcConnection)
+        ConnectionTerminationWatchdog::createConnectionTerminationWatchdog(m_xpcConnection, intervalInSeconds);
+}
+    
 void Connection::platformInitialize(Identifier identifier)
 {
 #if !PLATFORM(IOS)

Modified: trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp (169388 => 169389)


--- trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp	2014-05-27 17:36:21 UTC (rev 169388)
+++ trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp	2014-05-27 17:36:55 UTC (rev 169389)
@@ -210,6 +210,11 @@
     // We only allow this when using a network process, as otherwise the WebProcess needs to preserve its session state.
     if (m_context->usesNetworkProcess() && canTerminateChildProcess()) {
         abortProcessLaunchIfNeeded();
+#if PLATFORM(IOS)
+        // On iOS deploy a watchdog in the UI process, since the content may be suspended.
+        // 30s should be sufficient for any outstanding activity to complete cleanly.
+        connection()->terminateSoon(30);
+#endif
         disconnect();
     }
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to