Make sure implementation of InitializeWebKit2() always run on the main thread
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 May 2017 18:44:14 +0000 (18:44 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 May 2017 18:44:14 +0000 (18:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=172362
<rdar://problem/32295678>

Reviewed by Geoffrey Garen.

Add logic in InitializeWebKit2() for Cocoa ports to always run the initialization code
is only called once, and on the main thread. If we are called from a non-main thread,
we will dispatch synchronously to the main thread to run the initialization code.

This is needed because WebKit2Initialize() is called from the API::Object constructor.
API::Object is thread-safe RefCounted and those objects are sometimes initialized on
non-main thread. If the first of such objects happened to be initialized on a non-main
thread, then we would run the initialization code for the first time on a non-main
thread. This would lead to hard to debug issues because code such as
RunLoop::initializeMainRunLoop() is only safe to call on the main thread because it
stores a pointer to the current thread's RunLoop in a static variable for later use
(i.e. for RunLoop::main()).

* Shared/Cocoa/WebKit2InitializeCocoa.mm: Copied from Source/WebKit2/Shared/WebKit2Initialize.cpp.
(WebKit::runInitializationCode):
(WebKit::InitializeWebKit2):
* Shared/WebKit2Initialize.cpp:
(WebKit::InitializeWebKit2):
* WebKit2.xcodeproj/project.pbxproj:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@217137 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/Shared/Cocoa/WebKit2InitializeCocoa.mm [new file with mode: 0644]
Source/WebKit2/Shared/WebKit2Initialize.cpp
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj

index 6f0bb91..0e6b953 100644 (file)
@@ -1,3 +1,31 @@
+2017-05-19  Chris Dumez  <cdumez@apple.com>
+
+        Make sure implementation of InitializeWebKit2() always run on the main thread
+        https://bugs.webkit.org/show_bug.cgi?id=172362
+        <rdar://problem/32295678>
+
+        Reviewed by Geoffrey Garen.
+
+        Add logic in InitializeWebKit2() for Cocoa ports to always run the initialization code
+        is only called once, and on the main thread. If we are called from a non-main thread,
+        we will dispatch synchronously to the main thread to run the initialization code.
+
+        This is needed because WebKit2Initialize() is called from the API::Object constructor.
+        API::Object is thread-safe RefCounted and those objects are sometimes initialized on
+        non-main thread. If the first of such objects happened to be initialized on a non-main
+        thread, then we would run the initialization code for the first time on a non-main
+        thread. This would lead to hard to debug issues because code such as
+        RunLoop::initializeMainRunLoop() is only safe to call on the main thread because it
+        stores a pointer to the current thread's RunLoop in a static variable for later use
+        (i.e. for RunLoop::main()).
+
+        * Shared/Cocoa/WebKit2InitializeCocoa.mm: Copied from Source/WebKit2/Shared/WebKit2Initialize.cpp.
+        (WebKit::runInitializationCode):
+        (WebKit::InitializeWebKit2):
+        * Shared/WebKit2Initialize.cpp:
+        (WebKit::InitializeWebKit2):
+        * WebKit2.xcodeproj/project.pbxproj:
+
 2017-05-19  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         REGRESSION(r216977): [GTK] Ephemeral sessions broken after r216977
diff --git a/Source/WebKit2/Shared/Cocoa/WebKit2InitializeCocoa.mm b/Source/WebKit2/Shared/Cocoa/WebKit2InitializeCocoa.mm
new file mode 100644 (file)
index 0000000..464aa42
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "WebKit2Initialize.h"
+
+#import "LogInitialization.h"
+#import "WebSystemInterface.h"
+#import <WebCore/LogInitialization.h>
+#import <mutex>
+#import <runtime/InitializeThreading.h>
+#import <wtf/MainThread.h>
+#import <wtf/RunLoop.h>
+
+#if PLATFORM(IOS)
+#import <WebCore/WebCoreThreadSystemInterface.h>
+#endif
+
+namespace WebKit {
+
+static std::once_flag flag;
+
+static void runInitializationCode(void* = nullptr)
+{
+    InitWebCoreSystemInterface();
+#if PLATFORM(IOS)
+    InitWebCoreThreadSystemInterface();
+#endif
+
+    JSC::initializeThreading();
+    RunLoop::initializeMainRunLoop();
+
+#if !LOG_DISABLED || !RELEASE_LOG_DISABLED
+    WebCore::initializeLogChannelsIfNecessary();
+    WebKit::initializeLogChannelsIfNecessary();
+#endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
+}
+
+void InitializeWebKit2()
+{
+    // Make sure the initialization code is run only once and on the main thread since things like RunLoop::initializeMainRunLoop()
+    // are only safe to call on the main thread.
+    std::call_once(flag, [] {
+        if ([NSThread isMainThread])
+            runInitializationCode();
+        else
+            dispatch_sync_f(dispatch_get_main_queue(), nullptr, runInitializationCode);
+    });
+}
+
+}
index c5637c7..dad1bba 100644 (file)
 #include <wtf/MainThread.h>
 #include <wtf/RunLoop.h>
 
-#if PLATFORM(COCOA)
-#include "WebSystemInterface.h"
-#endif
-#if PLATFORM(IOS)
-#import <WebCore/WebCoreThreadSystemInterface.h>
-#endif
-
 namespace WebKit {
 
+#if !PLATFORM(COCOA)
+
 void InitializeWebKit2()
 {
-#if PLATFORM(COCOA)
-    InitWebCoreSystemInterface();
-#endif
-#if PLATFORM(IOS)
-    InitWebCoreThreadSystemInterface();
-#endif
-
     JSC::initializeThreading();
     RunLoop::initializeMainRunLoop();
 
@@ -59,4 +47,6 @@ void InitializeWebKit2()
 #endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
 }
 
+#endif // !PLATFORM(COCOA)
+
 } // namespace WebKit
index 049c182..4878318 100644 (file)
                4450AEC01DC3FAE5009943F2 /* SharedMemoryCocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4450AEBF1DC3FAE5009943F2 /* SharedMemoryCocoa.cpp */; };
                463FD4801EB9459600A2982C /* WKProcessTerminationReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 463FD47F1EB9458400A2982C /* WKProcessTerminationReason.h */; settings = {ATTRIBUTES = (Private, ); }; };
                463FD4821EB94EC000A2982C /* ProcessTerminationReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 463FD4811EB94EAD00A2982C /* ProcessTerminationReason.h */; };
+               465250E61ECF52DC002025CB /* WebKit2InitializeCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 465250E51ECF52CD002025CB /* WebKit2InitializeCocoa.mm */; };
                46A2B6081E5676A600C3DEDA /* BackgroundProcessResponsivenessTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46A2B6061E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.cpp */; };
                46A2B6091E5676A600C3DEDA /* BackgroundProcessResponsivenessTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */; };
                4A3CC18A19B063E700D14AEF /* UserMediaPermissionRequestManagerProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A410F3919AF7B04002EBAB5 /* UserMediaPermissionRequestManagerProxy.cpp */; };
                4450AEBF1DC3FAE5009943F2 /* SharedMemoryCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SharedMemoryCocoa.cpp; path = cocoa/SharedMemoryCocoa.cpp; sourceTree = "<group>"; };
                463FD47F1EB9458400A2982C /* WKProcessTerminationReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKProcessTerminationReason.h; sourceTree = "<group>"; };
                463FD4811EB94EAD00A2982C /* ProcessTerminationReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessTerminationReason.h; sourceTree = "<group>"; };
+               465250E51ECF52CD002025CB /* WebKit2InitializeCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebKit2InitializeCocoa.mm; sourceTree = "<group>"; };
                46A2B6061E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BackgroundProcessResponsivenessTimer.cpp; sourceTree = "<group>"; };
                46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackgroundProcessResponsivenessTimer.h; sourceTree = "<group>"; };
                4A410F3519AF7AC3002EBAB5 /* WKUserMediaPermissionRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKUserMediaPermissionRequest.cpp; sourceTree = "<group>"; };
                                378E1A3F181EDA010031007A /* WKObject.h */,
                                374436871820E7240049579F /* WKObject.mm */,
                                7AF236221E79A43100438A05 /* WebErrorsCocoa.mm */,
+                               465250E51ECF52CD002025CB /* WebKit2InitializeCocoa.mm */,
                        );
                        name = cocoa;
                        path = Cocoa;
                                BCE469791214F2B4000B98EB /* WebFrameListenerProxy.cpp in Sources */,
                                BC111A5F112F4FBB00337BAB /* WebFrameLoaderClient.cpp in Sources */,
                                2D28F3E71885CCC1004B9EAE /* WebFrameLoaderClientIOS.mm in Sources */,
+                               465250E61ECF52DC002025CB /* WebKit2InitializeCocoa.mm in Sources */,
                                9391F2CA121B679A00EBF7E8 /* WebFrameNetworkingContext.mm in Sources */,
                                BCB9F6A11123A84B00A137E0 /* WebFramePolicyListenerProxy.cpp in Sources */,
                                BC111B0E112F5E4F00337BAB /* WebFrameProxy.cpp in Sources */,