Title: [117094] trunk/Source/WebCore
Revision
117094
Author
[email protected]
Date
2012-05-15 11:00:13 -0700 (Tue, 15 May 2012)

Log Message

[Qt] WebKit with Qt5 hangs on Mac
https://bugs.webkit.org/show_bug.cgi?id=79785

Reviewed by Tor Arne Vestbø.

Delay the initialization of our QNetworkConfigurationManager used in
NetworkStateNotifierPrivate. On Mac it was causing a race condition because it
spawns a thread that triggers a static initializer in Qt, while in the main
thread NetworkStateNotifier is being static initialized. On Mac the lock for
static initializers is shared between all of them, causing a deadlock.

The issue was also reported in http://openradar.appspot.com/11217150.

* platform/network/qt/NetworkStateNotifierPrivate.h:
(NetworkStateNotifierPrivate):
(WebCore::NetworkStateNotifierPrivate::effectivelyOnline):
* platform/network/qt/NetworkStateNotifierQt.cpp:
(WebCore::NetworkStateNotifierPrivate::NetworkStateNotifierPrivate):
(WebCore::NetworkStateNotifierPrivate::setNetworkAccessAllowed):
(WebCore::NetworkStateNotifierPrivate::setOnlineState):
(WebCore::NetworkStateNotifierPrivate::initialize):
(WebCore):
(WebCore::NetworkStateNotifierPrivate::~NetworkStateNotifierPrivate):
(WebCore::NetworkStateNotifier::updateState):
(WebCore::NetworkStateNotifier::NetworkStateNotifier):
(WebCore::NetworkStateNotifier::setNetworkAccessAllowed):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (117093 => 117094)


--- trunk/Source/WebCore/ChangeLog	2012-05-15 17:56:37 UTC (rev 117093)
+++ trunk/Source/WebCore/ChangeLog	2012-05-15 18:00:13 UTC (rev 117094)
@@ -1,3 +1,32 @@
+2012-05-15  Caio Marcelo de Oliveira Filho  <[email protected]>
+
+        [Qt] WebKit with Qt5 hangs on Mac
+        https://bugs.webkit.org/show_bug.cgi?id=79785
+
+        Reviewed by Tor Arne Vestbø.
+
+        Delay the initialization of our QNetworkConfigurationManager used in
+        NetworkStateNotifierPrivate. On Mac it was causing a race condition because it
+        spawns a thread that triggers a static initializer in Qt, while in the main
+        thread NetworkStateNotifier is being static initialized. On Mac the lock for
+        static initializers is shared between all of them, causing a deadlock.
+
+        The issue was also reported in http://openradar.appspot.com/11217150.
+
+        * platform/network/qt/NetworkStateNotifierPrivate.h:
+        (NetworkStateNotifierPrivate):
+        (WebCore::NetworkStateNotifierPrivate::effectivelyOnline):
+        * platform/network/qt/NetworkStateNotifierQt.cpp:
+        (WebCore::NetworkStateNotifierPrivate::NetworkStateNotifierPrivate):
+        (WebCore::NetworkStateNotifierPrivate::setNetworkAccessAllowed):
+        (WebCore::NetworkStateNotifierPrivate::setOnlineState):
+        (WebCore::NetworkStateNotifierPrivate::initialize):
+        (WebCore):
+        (WebCore::NetworkStateNotifierPrivate::~NetworkStateNotifierPrivate):
+        (WebCore::NetworkStateNotifier::updateState):
+        (WebCore::NetworkStateNotifier::NetworkStateNotifier):
+        (WebCore::NetworkStateNotifier::setNetworkAccessAllowed):
+
 2012-05-15  Allan Sandfeld Jensen  <[email protected]>
 
         Factor HitTestPoint out of HitTestResult.

Modified: trunk/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h (117093 => 117094)


--- trunk/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h	2012-05-15 17:56:37 UTC (rev 117093)
+++ trunk/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h	2012-05-15 18:00:13 UTC (rev 117094)
@@ -21,6 +21,7 @@
 #define NetworkStateNotifierPrivate_h
 
 #include <QObject>
+#include <wtf/OwnPtr.h>
 
 QT_BEGIN_NAMESPACE
 class QNetworkConfigurationManager;
@@ -35,12 +36,18 @@
 public:
     NetworkStateNotifierPrivate(NetworkStateNotifier* notifier);
     ~NetworkStateNotifierPrivate();
+
+    void setNetworkAccessAllowed(bool);
+    bool effectivelyOnline() const { return m_online && m_networkAccessAllowed; }
+
 public slots:
-    void onlineStateChanged(bool);
-    void networkAccessPermissionChanged(bool);
+    void setOnlineState(bool);
 
+private slots:
+    void initialize();
+
 public:
-    QNetworkConfigurationManager* m_configurationManager;
+    OwnPtr<QNetworkConfigurationManager> m_configurationManager;
     bool m_online;
     bool m_networkAccessAllowed;
     NetworkStateNotifier* m_notifier;

Modified: trunk/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp (117093 => 117094)


--- trunk/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp	2012-05-15 17:56:37 UTC (rev 117093)
+++ trunk/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp	2012-05-15 18:00:13 UTC (rev 117094)
@@ -23,51 +23,62 @@
 #if (PLATFORM(QT) && !defined(QT_NO_BEARERMANAGEMENT))
 
 #include "NetworkStateNotifierPrivate.h"
-#include "qnetworkconfigmanager.h"
+#include <QNetworkConfigurationManager>
+#include <QTimer>
+#include <wtf/PassOwnPtr.h>
 
 namespace WebCore {
 
 NetworkStateNotifierPrivate::NetworkStateNotifierPrivate(NetworkStateNotifier* notifier)
-    : m_configurationManager(new QNetworkConfigurationManager())
-    , m_online(m_configurationManager->isOnline())
+    : m_online(false)
     , m_networkAccessAllowed(true)
     , m_notifier(notifier)
 {
-    Q_ASSERT(notifier);
-    connect(m_configurationManager, SIGNAL(onlineStateChanged(bool)), this, SLOT(onlineStateChanged(bool)));
+    ASSERT(notifier);
+
+    // Initialization is delayed because QNetworkConfigurationManager starts a new thread that causes
+    // deadlock on Mac because all the static initializers share the same lock. Both NetworkStateNotifier and Qt internals
+    // triggered in new thread use static initializer. See also: http://openradar.appspot.com/11217150.
+    QTimer::singleShot(0, this, SLOT(initialize()));
 }
 
-void NetworkStateNotifierPrivate::onlineStateChanged(bool isOnline)
+void NetworkStateNotifierPrivate::setNetworkAccessAllowed(bool isAllowed)
 {
-    if (m_online == isOnline)
+    if (isAllowed == m_networkAccessAllowed)
         return;
 
-    m_online = isOnline;
-    if (m_networkAccessAllowed)
+    m_networkAccessAllowed = isAllowed;
+    if (m_online)
         m_notifier->updateState();
 }
 
-void NetworkStateNotifierPrivate::networkAccessPermissionChanged(bool isAllowed)
+void NetworkStateNotifierPrivate::setOnlineState(bool isOnline)
 {
-    if (isAllowed == m_networkAccessAllowed)
+    if (m_online == isOnline)
         return;
 
-    m_networkAccessAllowed = isAllowed;
-    if (m_online)
+    m_online = isOnline;
+    if (m_networkAccessAllowed)
         m_notifier->updateState();
 }
 
+void NetworkStateNotifierPrivate::initialize()
+{
+    m_configurationManager = adoptPtr(new QNetworkConfigurationManager());
+    setOnlineState(m_configurationManager->isOnline());
+    connect(m_configurationManager.get(), SIGNAL(onlineStateChanged(bool)), this, SLOT(setOnlineState(bool)));
+}
+
 NetworkStateNotifierPrivate::~NetworkStateNotifierPrivate()
 {
-    delete m_configurationManager;
 }
 
 void NetworkStateNotifier::updateState()
 {
-    if (m_isOnLine == (p->m_online && p->m_networkAccessAllowed))
+    if (m_isOnLine == p->effectivelyOnline())
         return;
 
-    m_isOnLine = p->m_online && p->m_networkAccessAllowed;
+    m_isOnLine = p->effectivelyOnline();
     if (m_networkStateChangedFunction)
         m_networkStateChangedFunction();
 }
@@ -77,12 +88,12 @@
     , m_networkStateChangedFunction(0)
 {
     p = new NetworkStateNotifierPrivate(this);
-    m_isOnLine = p->m_online && p->m_networkAccessAllowed;
+    m_isOnLine = p->effectivelyOnline();
 }
 
 void NetworkStateNotifier::setNetworkAccessAllowed(bool isAllowed)
 {
-    p->networkAccessPermissionChanged(isAllowed);
+    p->setNetworkAccessAllowed(isAllowed);
 }
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to