Title: [165040] trunk/Source/_javascript_Core
Revision
165040
Author
commit-qu...@webkit.org
Date
2014-03-03 22:57:59 -0800 (Mon, 03 Mar 2014)

Log Message

Web Inspector: Avoid too early deref caused by RemoteInspectorXPCConnection::close
https://bugs.webkit.org/show_bug.cgi?id=129631

Patch by Joseph Pecoraro <pecor...@apple.com> on 2014-03-03
Reviewed by Timothy Hatcher.

Avoid deref() too early if a client calls close(). The xpc_connection_close
will cause another XPC_ERROR event to come in from the queue, deref then.
Likewise, protect multithreaded access to m_client. If a client calls
close() we want to immediately clear the pointer to prevent calls to it.

Overall the multi-threading aspects of RemoteInspectorXPCConnection are
growing too complicated for probably little benefit. We may want to
clean this up later.

* inspector/remote/RemoteInspector.mm:
(Inspector::RemoteInspector::xpcConnectionFailed):
* inspector/remote/RemoteInspectorXPCConnection.h:
* inspector/remote/RemoteInspectorXPCConnection.mm:
(Inspector::RemoteInspectorXPCConnection::RemoteInspectorXPCConnection):
(Inspector::RemoteInspectorXPCConnection::close):
(Inspector::RemoteInspectorXPCConnection::closeOnQueue):
(Inspector::RemoteInspectorXPCConnection::deserializeMessage):
(Inspector::RemoteInspectorXPCConnection::handleEvent):
(Inspector::RemoteInspectorXPCConnection::sendMessage):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (165039 => 165040)


--- trunk/Source/_javascript_Core/ChangeLog	2014-03-04 06:52:56 UTC (rev 165039)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-03-04 06:57:59 UTC (rev 165040)
@@ -1,3 +1,30 @@
+2014-03-03  Joseph Pecoraro  <pecor...@apple.com>
+
+        Web Inspector: Avoid too early deref caused by RemoteInspectorXPCConnection::close
+        https://bugs.webkit.org/show_bug.cgi?id=129631
+
+        Reviewed by Timothy Hatcher.
+
+        Avoid deref() too early if a client calls close(). The xpc_connection_close
+        will cause another XPC_ERROR event to come in from the queue, deref then.
+        Likewise, protect multithreaded access to m_client. If a client calls
+        close() we want to immediately clear the pointer to prevent calls to it.
+
+        Overall the multi-threading aspects of RemoteInspectorXPCConnection are
+        growing too complicated for probably little benefit. We may want to
+        clean this up later.
+
+        * inspector/remote/RemoteInspector.mm:
+        (Inspector::RemoteInspector::xpcConnectionFailed):
+        * inspector/remote/RemoteInspectorXPCConnection.h:
+        * inspector/remote/RemoteInspectorXPCConnection.mm:
+        (Inspector::RemoteInspectorXPCConnection::RemoteInspectorXPCConnection):
+        (Inspector::RemoteInspectorXPCConnection::close):
+        (Inspector::RemoteInspectorXPCConnection::closeOnQueue):
+        (Inspector::RemoteInspectorXPCConnection::deserializeMessage):
+        (Inspector::RemoteInspectorXPCConnection::handleEvent):
+        (Inspector::RemoteInspectorXPCConnection::sendMessage):
+
 2014-03-03  Michael Saboff  <msab...@apple.com>
 
         AbstractMacroAssembler::CachedTempRegister should start out invalid

Modified: trunk/Source/_javascript_Core/inspector/remote/RemoteInspector.mm (165039 => 165040)


--- trunk/Source/_javascript_Core/inspector/remote/RemoteInspector.mm	2014-03-04 06:52:56 UTC (rev 165039)
+++ trunk/Source/_javascript_Core/inspector/remote/RemoteInspector.mm	2014-03-04 06:57:59 UTC (rev 165040)
@@ -265,6 +265,8 @@
 void RemoteInspector::xpcConnectionFailed(RemoteInspectorXPCConnection* connection)
 {
     std::lock_guard<std::mutex> lock(m_mutex);
+
+    ASSERT(connection == m_xpcConnection);
     if (connection != m_xpcConnection)
         return;
 
@@ -276,10 +278,8 @@
 
     updateHasActiveDebugSession();
 
-    if (m_xpcConnection) {
-        m_xpcConnection->close();
-        m_xpcConnection = nullptr;
-    }
+    // The connection will close itself.
+    m_xpcConnection = nullptr;
 }
 
 void RemoteInspector::xpcConnectionUnhandledMessage(RemoteInspectorXPCConnection*, xpc_object_t)

Modified: trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorXPCConnection.h (165039 => 165040)


--- trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorXPCConnection.h	2014-03-04 06:52:56 UTC (rev 165039)
+++ trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorXPCConnection.h	2014-03-04 06:57:59 UTC (rev 165040)
@@ -29,6 +29,7 @@
 #define RemoteInspectorXPCConnection_h
 
 #import <dispatch/dispatch.h>
+#import <mutex>
 #import <wtf/ThreadSafeRefCounted.h>
 #import <xpc/xpc.h>
 
@@ -56,7 +57,12 @@
 private:
     NSDictionary *deserializeMessage(xpc_object_t);
     void handleEvent(xpc_object_t);
+    void closeOnQueue();
 
+    // We handle XPC events on the queue, but a client may call close() on any queue.
+    // We make sure that m_client is thread safe and immediately cleared in close().
+    std::mutex m_mutex;
+
     xpc_connection_t m_connection;
     dispatch_queue_t m_queue;
     Client* m_client;

Modified: trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorXPCConnection.mm (165039 => 165040)


--- trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorXPCConnection.mm	2014-03-04 06:52:56 UTC (rev 165039)
+++ trunk/Source/_javascript_Core/inspector/remote/RemoteInspectorXPCConnection.mm	2014-03-04 06:57:59 UTC (rev 165040)
@@ -30,6 +30,7 @@
 
 #import <Foundation/Foundation.h>
 #import <wtf/Assertions.h>
+#import <wtf/Ref.h>
 
 #if __has_include(<CoreFoundation/CFXPCBridge.h>)
 #import <CoreFoundation/CFXPCBridge.h>
@@ -59,7 +60,7 @@
         handleEvent(object);
     });
 
-    // Balanced by deref in close.
+    // Balanced by deref when the xpc_connection receives XPC_ERROR.
     ref();
 
     xpc_connection_resume(m_connection);
@@ -74,24 +75,30 @@
 
 void RemoteInspectorXPCConnection::close()
 {
-    if (m_closed)
-        return;
+    std::lock_guard<std::mutex> lock(m_mutex);
 
     m_closed = true;
+    m_client = nullptr;
 
     dispatch_async(m_queue, ^{
+        std::lock_guard<std::mutex> lock(m_mutex);
+        // This will trigger one last XPC_ERROR_CONNECTION_INVALID event on the queue and deref us.
+        closeOnQueue();
+    });
+}
+
+void RemoteInspectorXPCConnection::closeOnQueue()
+{
+    if (m_connection) {
         xpc_connection_cancel(m_connection);
         xpc_release(m_connection);
         m_connection = NULL;
+    }
 
+    if (m_queue) {
         dispatch_release(m_queue);
         m_queue = NULL;
-
-        m_client = nullptr;
-
-        // Balance the ref in our constructor.
-        deref();
-    });
+    }
 }
 
 NSDictionary *RemoteInspectorXPCConnection::deserializeMessage(xpc_object_t object)
@@ -101,6 +108,7 @@
 
     xpc_object_t xpcDictionary = xpc_dictionary_get_value(object, RemoteInspectorXPCConnectionSerializedMessageKey);
     if (!xpcDictionary || xpc_get_type(xpcDictionary) != XPC_TYPE_DICTIONARY) {
+        std::lock_guard<std::mutex> lock(m_mutex);
         if (m_client)
             m_client->xpcConnectionUnhandledMessage(this, object);
         return nil;
@@ -114,8 +122,17 @@
 void RemoteInspectorXPCConnection::handleEvent(xpc_object_t object)
 {
     if (xpc_get_type(object) == XPC_TYPE_ERROR) {
+        std::lock_guard<std::mutex> lock(m_mutex);
         if (m_client)
             m_client->xpcConnectionFailed(this);
+
+        m_closed = true;
+        m_client = nullptr;
+        closeOnQueue();
+
+        // This is the last event we will ever receive from the connection.
+        // Balance the ref() in the constructor.
+        deref();
         return;
     }
 
@@ -125,12 +142,14 @@
 
     NSString *message = [dataDictionary objectForKey:RemoteInspectorXPCConnectionMessageNameKey];
     NSDictionary *userInfo = [dataDictionary objectForKey:RemoteInspectorXPCConnectionUserInfoKey];
+    std::lock_guard<std::mutex> lock(m_mutex);
     if (m_client)
         m_client->xpcConnectionReceivedMessage(this, message, userInfo);
 }
 
 void RemoteInspectorXPCConnection::sendMessage(NSString *messageName, NSDictionary *userInfo)
 {
+    ASSERT(!m_closed);
     if (m_closed)
         return;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to