Title: [215638] trunk

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (215637 => 215638)


--- trunk/Source/_javascript_Core/ChangeLog	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-04-21 21:28:17 UTC (rev 215638)
@@ -1,3 +1,15 @@
+2017-04-21  Keith Miller  <[email protected]>
+
+        Unreviewed, rolling out r215634.
+
+        underlying build issues should have been fixed
+
+        Reverted changeset:
+
+        "Unreviewed, rolling out r215620 and r215623."
+        https://bugs.webkit.org/show_bug.cgi?id=171139
+        http://trac.webkit.org/changeset/215634
+
 2017-04-21  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r215620 and r215623.

Modified: trunk/Source/_javascript_Core/jit/ExecutableAllocator.h (215637 => 215638)


--- trunk/Source/_javascript_Core/jit/ExecutableAllocator.h	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/_javascript_Core/jit/ExecutableAllocator.h	2017-04-21 21:28:17 UTC (rev 215638)
@@ -81,6 +81,12 @@
 extern JS_EXPORTDATA uintptr_t startOfFixedExecutableMemoryPool;
 extern JS_EXPORTDATA uintptr_t endOfFixedExecutableMemoryPool;
 
+inline bool isJITPC(void* pc)
+{
+    return reinterpret_cast<void*>(startOfFixedExecutableMemoryPool) <= pc
+        && pc < reinterpret_cast<void*>(endOfFixedExecutableMemoryPool);
+}
+
 typedef void (*JITWriteSeparateHeapsFunction)(off_t, const void*, size_t);
 extern JS_EXPORTDATA JITWriteSeparateHeapsFunction jitWriteSeparateHeapsFunction;
 
@@ -143,6 +149,9 @@
     ~ExecutableAllocator();
 };
 
+#else
+inline bool isJITPC(void*) { return false; }
 #endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
 
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/VMTraps.cpp (215637 => 215638)


--- trunk/Source/_javascript_Core/runtime/VMTraps.cpp	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/_javascript_Core/runtime/VMTraps.cpp	2017-04-21 21:28:17 UTC (rev 215638)
@@ -40,11 +40,9 @@
 #include "VMInspector.h"
 #include "Watchdog.h"
 #include <wtf/ProcessID.h>
+#include <wtf/ThreadMessage.h>
+#include <wtf/threads/Signals.h>
 
-#if OS(DARWIN)
-#include <signal.h>
-#endif
-
 namespace JSC {
 
 ALWAYS_INLINE VM& VMTraps::vm() const
@@ -54,9 +52,6 @@
 
 #if ENABLE(SIGNAL_BASED_VM_TRAPS)
 
-struct sigaction originalSigusr1Action;
-struct sigaction originalSigtrapAction;
-
 struct SignalContext {
     SignalContext(mcontext_t& mcontext)
         : mcontext(mcontext)
@@ -132,89 +127,37 @@
     return VMAndStackBounds { activeVM, stackBounds };
 }
 
-static void handleSigusr1(int signalNumber, siginfo_t* info, void* uap)
+static void installSignalHandler()
 {
-    SignalContext context(static_cast<ucontext_t*>(uap)->uc_mcontext);
-    auto activeVMAndStackBounds = findActiveVMAndStackBounds(context);
-    if (activeVMAndStackBounds) {
+    installSignalHandler(Signal::Trap, [] (int, siginfo_t*, void* uap) -> SignalAction {
+        SignalContext context(static_cast<ucontext_t*>(uap)->uc_mcontext);
+
+        if (!isJITPC(context.trapPC))
+            return SignalAction::NotHandled;
+
+        // FIXME: This currently eats all traps including jit asserts we should make sure this
+        // always works. https://bugs.webkit.org/show_bug.cgi?id=171039
+        auto activeVMAndStackBounds = findActiveVMAndStackBounds(context);
+        if (!activeVMAndStackBounds)
+            return SignalAction::Handled; // Let the SignalSender try again later.
+
         VM* vm = activeVMAndStackBounds.value().vm;
         if (vm) {
-            StackBounds stackBounds = activeVMAndStackBounds.value().stackBounds;
             VMTraps& traps = vm->traps();
-            if (traps.needTrapHandling())
-                traps.tryInstallTrapBreakpoints(context, stackBounds);
+            if (!traps.needTrapHandling())
+                return SignalAction::Handled; // The polling code beat us to handling the trap already.
+
+            auto expectedSuccess = traps.tryJettisonCodeBlocksOnStack(context);
+            if (!expectedSuccess)
+                return SignalAction::Handled; // Let the SignalSender try again later.
+            if (expectedSuccess.value())
+                return SignalAction::Handled; // We've success jettison the codeBlocks.
         }
-    }
 
-    auto originalAction = originalSigusr1Action.sa_sigaction;
-    if (originalAction)
-        originalAction(signalNumber, info, uap);
+        return SignalAction::Handled;
+    });
 }
 
-static void handleSigtrap(int signalNumber, siginfo_t* info, void* uap)
-{
-    SignalContext context(static_cast<ucontext_t*>(uap)->uc_mcontext);
-    auto activeVMAndStackBounds = findActiveVMAndStackBounds(context);
-    if (!activeVMAndStackBounds)
-        return; // Let the SignalSender try again later.
-
-    VM* vm = activeVMAndStackBounds.value().vm;
-    if (vm) {
-        VMTraps& traps = vm->traps();
-        if (!traps.needTrapHandling())
-            return; // The polling code beat us to handling the trap already.
-
-        auto expectedSuccess = traps.tryJettisonCodeBlocksOnStack(context);
-        if (!expectedSuccess)
-            return; // Let the SignalSender try again later.
-        if (expectedSuccess.value())
-            return; // We've success jettison the codeBlocks.
-    }
-
-    // If we get here, then this SIGTRAP is not due to a VMTrap. Let's do the default action.
-    auto originalAction = originalSigtrapAction.sa_sigaction;
-    if (originalAction) {
-        // It is always safe to just invoke the original handler using the sa_sigaction form
-        // without checking for the SA_SIGINFO flag. If the original handler is of the
-        // sa_handler form, it will just ignore the 2nd and 3rd arguments since sa_handler is a
-        // subset of sa_sigaction. This is what the man pages says the OS does anyway.
-        originalAction(signalNumber, info, uap);
-    }
-    
-    // Pre-emptively restore the default handler but we may roll it back below.
-    struct sigaction currentAction;
-    struct sigaction defaultAction;
-    defaultAction.sa_handler = SIG_DFL;
-    sigfillset(&defaultAction.sa_mask);
-    defaultAction.sa_flags = 0;
-    sigaction(SIGTRAP, &defaultAction, &currentAction);
-    
-    if (currentAction.sa_sigaction != handleSigtrap) {
-        // This means that there's a client handler installed after us. This also means
-        // that the client handler thinks it was able to recover from the SIGTRAP, and
-        // did not uninstall itself. We can't argue with this because the signal isn't
-        // known to be from a VMTraps signal. Hence, restore the client handler
-        // and keep going.
-        sigaction(SIGTRAP, &currentAction, nullptr);
-    }
-}
-
-static void installSignalHandlers()
-{
-    typedef void (* SigactionHandler)(int, siginfo_t *, void *);
-    struct sigaction action;
-
-    action.sa_sigaction = reinterpret_cast<SigactionHandler>(handleSigusr1);
-    sigfillset(&action.sa_mask);
-    action.sa_flags = SA_SIGINFO;
-    sigaction(SIGUSR1, &action, &originalSigusr1Action);
-
-    action.sa_sigaction = reinterpret_cast<SigactionHandler>(handleSigtrap);
-    sigfillset(&action.sa_mask);
-    action.sa_flags = SA_SIGINFO;
-    sigaction(SIGTRAP, &action, &originalSigtrapAction);
-}
-
 ALWAYS_INLINE static CallFrame* sanitizedTopCallFrame(CallFrame* topCallFrame)
 {
 #if !defined(NDEBUG) && !CPU(ARM) && !CPU(MIPS)
@@ -400,7 +343,7 @@
     if (!Options::usePollingTraps()) {
         static std::once_flag once;
         std::call_once(once, [] {
-            installSignalHandlers();
+            installSignalHandler();
         });
     }
 #endif
@@ -460,7 +403,19 @@
             VM& vm = *m_vm;
             auto optionalOwnerThread = vm.ownerThread();
             if (optionalOwnerThread) {
-                optionalOwnerThread.value()->signal(SIGUSR1);
+                sendMessage(*optionalOwnerThread.value().get(), [] (siginfo_t*, ucontext_t* ucontext) -> void {
+                    SignalContext context(ucontext->uc_mcontext);
+                    auto activeVMAndStackBounds = findActiveVMAndStackBounds(context);
+                    if (activeVMAndStackBounds) {
+                        VM* vm = activeVMAndStackBounds.value().vm;
+                        if (vm) {
+                            StackBounds stackBounds = activeVMAndStackBounds.value().stackBounds;
+                            VMTraps& traps = vm->traps();
+                            if (traps.needTrapHandling())
+                                traps.tryInstallTrapBreakpoints(context, stackBounds);
+                        }
+                    }
+                });
                 break;
             }
 

Modified: trunk/Source/_javascript_Core/runtime/VMTraps.h (215637 => 215638)


--- trunk/Source/_javascript_Core/runtime/VMTraps.h	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/_javascript_Core/runtime/VMTraps.h	2017-04-21 21:28:17 UTC (rev 215638)
@@ -42,7 +42,8 @@
 public:
     enum class Error {
         None,
-        LockUnavailable
+        LockUnavailable,
+        NotJITCode
     };
 
     enum EventType {

Modified: trunk/Source/_javascript_Core/tools/SigillCrashAnalyzer.cpp (215637 => 215638)


--- trunk/Source/_javascript_Core/tools/SigillCrashAnalyzer.cpp	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/_javascript_Core/tools/SigillCrashAnalyzer.cpp	2017-04-21 21:28:17 UTC (rev 215638)
@@ -37,9 +37,7 @@
 #include "A64DOpcode.h"
 #endif
 
-#if HAVE(SIGNAL_H)
-#include <signal.h>
-#endif
+#include <wtf/threads/Signals.h>
 
 namespace JSC {
 
@@ -141,60 +139,19 @@
     void* framePointer;
 };
 
-struct sigaction originalSigIllAction;
-
-static void handleCrash(int signalNumber, siginfo_t* info, void* uap)
+static void installCrashHandler()
 {
-    SignalContext context(static_cast<ucontext_t*>(uap)->uc_mcontext);
-    SigillCrashAnalyzer& analyzer = SigillCrashAnalyzer::instance();
-    auto crashSource = analyzer.analyze(context);
+#if CPU(X86_64) || CPU(ARM64)
+    installSignalHandler(Signal::Ill, [] (int, siginfo_t*, void* uap) {
+        SignalContext context(static_cast<ucontext_t*>(uap)->uc_mcontext);
 
-    auto originalAction = originalSigIllAction.sa_sigaction;
-    if (originalAction) {
-        // It is always safe to just invoke the original handler using the sa_sigaction form
-        // without checking for the SA_SIGINFO flag. If the original handler is of the
-        // sa_handler form, it will just ignore the 2nd and 3rd arguments since sa_handler is a
-        // subset of sa_sigaction. This is what the man pages says the OS does anyway.
-        originalAction(signalNumber, info, uap);
-    }
+        if (!isJITPC(context.machinePC))
+            return SignalAction::NotHandled;
 
-    if (crashSource == SigillCrashAnalyzer::CrashSource::_javascript_Core) {
-        // Restore the default handler so that we can get a core dump.
-        struct sigaction defaultAction;
-        defaultAction.sa_handler = SIG_DFL;
-        sigfillset(&defaultAction.sa_mask);
-        defaultAction.sa_flags = 0;
-        sigaction(SIGILL, &defaultAction, nullptr);
-    } else if (!originalAction) {
-        // Pre-emptively restore the default handler but we may roll it back below.
-        struct sigaction currentAction;
-        struct sigaction defaultAction;
-        defaultAction.sa_handler = SIG_DFL;
-        sigfillset(&defaultAction.sa_mask);
-        defaultAction.sa_flags = 0;
-        sigaction(SIGILL, &defaultAction, &currentAction);
-
-        if (currentAction.sa_sigaction != handleCrash) {
-            // This means that there's a client handler installed after us. This also means
-            // that the client handler thinks it was able to recover from the SIGILL, and
-            // did not uninstall itself. We can't argue with this because the crash isn't
-            // known to be from a _javascript_Core source. Hence, restore the client handler
-            // and keep going.
-            sigaction(SIGILL, &currentAction, nullptr);
-        }
-    }
-}
-
-static void installCrashHandler()
-{
-#if CPU(X86_64) || CPU(ARM64)
-    struct sigaction action;
-    action.sa_sigaction = reinterpret_cast<void (*)(int, siginfo_t *, void *)>(handleCrash);
-    sigfillset(&action.sa_mask);
-    action.sa_flags = SA_SIGINFO;
-    sigaction(SIGILL, &action, &originalSigIllAction);
-#else
-    UNUSED_PARAM(handleCrash);
+        SigillCrashAnalyzer& analyzer = SigillCrashAnalyzer::instance();
+        analyzer.analyze(context);
+        return SignalAction::NotHandled;
+    });
 #endif
 }
 

Modified: trunk/Source/_javascript_Core/wasm/WasmFaultSignalHandler.cpp (215637 => 215638)


--- trunk/Source/_javascript_Core/wasm/WasmFaultSignalHandler.cpp	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/_javascript_Core/wasm/WasmFaultSignalHandler.cpp	2017-04-21 21:28:17 UTC (rev 215638)
@@ -35,9 +35,9 @@
 #include "WasmMemory.h"
 #include "WasmThunks.h"
 
-#include <signal.h>
 #include <wtf/Lock.h>
 #include <wtf/NeverDestroyed.h>
+#include <wtf/threads/Signals.h>
 
 namespace JSC { namespace Wasm {
 
@@ -50,11 +50,9 @@
 
 #if ENABLE(WEBASSEMBLY_FAST_MEMORY)
 
-static struct sigaction oldSigBusHandler;
-static struct sigaction oldSigSegvHandler;
 static bool fastHandlerInstalled { false };
 
-static void trapHandler(int signal, siginfo_t* sigInfo, void* ucontext)
+static SignalAction trapHandler(int, siginfo_t* sigInfo, void* ucontext)
 {
     mcontext_t& context = static_cast<ucontext_t*>(ucontext)->uc_mcontext;
     void* faultingInstruction = MachineContext::instructionPointer(context);
@@ -63,9 +61,7 @@
     dataLogLnIf(verbose, "JIT memory start: ", RawPointer(reinterpret_cast<void*>(startOfFixedExecutableMemoryPool)), " end: ", RawPointer(reinterpret_cast<void*>(endOfFixedExecutableMemoryPool)));
     // First we need to make sure we are in JIT code before we can aquire any locks. Otherwise,
     // we might have crashed in code that is already holding one of the locks we want to aquire.
-    if (reinterpret_cast<void*>(startOfFixedExecutableMemoryPool) <= faultingInstruction
-        && faultingInstruction < reinterpret_cast<void*>(endOfFixedExecutableMemoryPool)) {
-
+    if (isJITPC(faultingInstruction)) {
         bool faultedInActiveFastMemory = false;
         {
             void* faultingAddress = sigInfo->si_addr;
@@ -89,17 +85,12 @@
                     dataLogLnIf(verbose, "found stub: ", RawPointer(exceptionStub.code().executableAddress()));
                     MachineContext::argumentPointer<1>(context) = reinterpret_cast<void*>(ExceptionType::OutOfBoundsMemoryAccess);
                     MachineContext::instructionPointer(context) = exceptionStub.code().executableAddress();
-                    return;
+                    return SignalAction::Handled;
                 }
             }
         }
     }
-
-    // Since we only use fast memory in processes we control, if we restore we will just fall back to the default handler.
-    if (signal == SIGBUS)
-        sigaction(signal, &oldSigBusHandler, nullptr);
-    else
-        sigaction(signal, &oldSigSegvHandler, nullptr);
+    return SignalAction::NotHandled;
 }
 
 #endif // ENABLE(WEBASSEMBLY_FAST_MEMORY)
@@ -133,23 +124,14 @@
             return;
 
 #if ENABLE(WEBASSEMBLY_FAST_MEMORY)
-        struct sigaction action;
+        installSignalHandler(Signal::Bus, [] (int signal, siginfo_t* sigInfo, void* ucontext) {
+            return trapHandler(signal, sigInfo, ucontext);
+        });
 
-        action.sa_sigaction = trapHandler;
-        sigfillset(&action.sa_mask);
-        action.sa_flags = SA_SIGINFO;
-        
-        // Installing signal handlers fails when
-        // 1. specificied sig is incorrect (invalid values or signal numbers which cannot be handled), or
-        // 2. second or third parameter points incorrect pointers.
-        // Thus, we must not fail in the following attempts.
-        int ret = 0;
-        ret = sigaction(SIGBUS, &action, &oldSigBusHandler);
-        RELEASE_ASSERT(!ret);
+        installSignalHandler(Signal::SegV, [] (int signal, siginfo_t* sigInfo, void* ucontext) {
+            return trapHandler(signal, sigInfo, ucontext);
+        });
 
-        ret = sigaction(SIGSEGV, &action, &oldSigSegvHandler);
-        RELEASE_ASSERT(!ret);
-
         codeLocations.construct();
         fastHandlerInstalled = true;
 #endif // ENABLE(WEBASSEMBLY_FAST_MEMORY)

Modified: trunk/Source/WTF/ChangeLog (215637 => 215638)


--- trunk/Source/WTF/ChangeLog	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/WTF/ChangeLog	2017-04-21 21:28:17 UTC (rev 215638)
@@ -1,5 +1,17 @@
 2017-04-21  Keith Miller  <[email protected]>
 
+        Unreviewed, rolling out r215634.
+
+        underlying build issues should have been fixed
+
+        Reverted changeset:
+
+        "Unreviewed, rolling out r215620 and r215623."
+        https://bugs.webkit.org/show_bug.cgi?id=171139
+        http://trac.webkit.org/changeset/215634
+
+2017-04-21  Keith Miller  <[email protected]>
+
         Remove LL/SC from Atomics
         https://bugs.webkit.org/show_bug.cgi?id=171141
 

Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (215637 => 215638)


--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2017-04-21 21:28:17 UTC (rev 215638)
@@ -149,6 +149,11 @@
 		515F79501CFC9F4A00CCED93 /* CrossThreadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 515F794D1CFC9F4A00CCED93 /* CrossThreadTask.h */; };
 		515F79561CFD3A6900CCED93 /* CrossThreadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 515F79551CFD3A6900CCED93 /* CrossThreadQueue.h */; };
 		52183012C99E476A84EEBEA8 /* SymbolImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F72BBDB107FA424886178B9E /* SymbolImpl.cpp */; };
+		5311BD531EA71CAD00525281 /* Signals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5311BD511EA71CAD00525281 /* Signals.cpp */; };
+		5311BD561EA7E15A00525281 /* LocklessBag.h in Headers */ = {isa = PBXBuildFile; fileRef = 5311BD551EA7E15A00525281 /* LocklessBag.h */; };
+		5311BD581EA7E1A100525281 /* Signals.h in Headers */ = {isa = PBXBuildFile; fileRef = 5311BD571EA7E1A100525281 /* Signals.h */; };
+		5311BD5A1EA81A9600525281 /* ThreadMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 5311BD591EA81A9600525281 /* ThreadMessage.h */; };
+		5311BD5C1EA822F900525281 /* ThreadMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5311BD5B1EA822F900525281 /* ThreadMessage.cpp */; };
 		539EB0631D55284200C82EF7 /* LEBDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 539EB0621D55284200C82EF7 /* LEBDecoder.h */; };
 		53EC253E1E95AD30000831B9 /* PriorityQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EC253C1E95AD30000831B9 /* PriorityQueue.h */; };
 		553071CA1C40427200384898 /* TinyLRUCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 553071C91C40427200384898 /* TinyLRUCache.h */; };
@@ -548,6 +553,11 @@
 		515F794C1CFC9F4A00CCED93 /* CrossThreadCopier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossThreadCopier.h; sourceTree = "<group>"; };
 		515F794D1CFC9F4A00CCED93 /* CrossThreadTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossThreadTask.h; sourceTree = "<group>"; };
 		515F79551CFD3A6900CCED93 /* CrossThreadQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossThreadQueue.h; sourceTree = "<group>"; };
+		5311BD511EA71CAD00525281 /* Signals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Signals.cpp; sourceTree = "<group>"; };
+		5311BD551EA7E15A00525281 /* LocklessBag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocklessBag.h; sourceTree = "<group>"; };
+		5311BD571EA7E1A100525281 /* Signals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Signals.h; sourceTree = "<group>"; };
+		5311BD591EA81A9600525281 /* ThreadMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadMessage.h; sourceTree = "<group>"; };
+		5311BD5B1EA822F900525281 /* ThreadMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadMessage.cpp; sourceTree = "<group>"; };
 		539EB0621D55284200C82EF7 /* LEBDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LEBDecoder.h; sourceTree = "<group>"; };
 		53EC253C1E95AD30000831B9 /* PriorityQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PriorityQueue.h; sourceTree = "<group>"; };
 		553071C91C40427200384898 /* TinyLRUCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyLRUCache.h; sourceTree = "<group>"; };
@@ -1064,6 +1074,7 @@
 				0F60F32D1DFCBD1B00416D6C /* LockedPrintStream.cpp */,
 				0F60F32E1DFCBD1B00416D6C /* LockedPrintStream.h */,
 				A8A472C3151A825A004123FF /* Locker.h */,
+				5311BD551EA7E15A00525281 /* LocklessBag.h */,
 				513E170A1CD7D5BF00E3650B /* LoggingAccumulator.h */,
 				0F30BA8C1E78708E002CA847 /* LoggingHashID.h */,
 				0F30BA8D1E78708E002CA847 /* LoggingHashMap.h */,
@@ -1189,6 +1200,8 @@
 				E3200AB51E9A536D003B59D2 /* ThreadHolder.cpp */,
 				E3200AB61E9A536D003B59D2 /* ThreadHolder.h */,
 				A8A47330151A825B004123FF /* ThreadHolderPthreads.cpp */,
+				5311BD5B1EA822F900525281 /* ThreadMessage.cpp */,
+				5311BD591EA81A9600525281 /* ThreadMessage.h */,
 				A8A47332151A825B004123FF /* Threading.cpp */,
 				A8A47333151A825B004123FF /* Threading.h */,
 				A8A47335151A825B004123FF /* ThreadingPrimitives.h */,
@@ -1316,6 +1329,8 @@
 			children = (
 				A8A4733A151A825B004123FF /* BinarySemaphore.cpp */,
 				A8A4733B151A825B004123FF /* BinarySemaphore.h */,
+				5311BD511EA71CAD00525281 /* Signals.cpp */,
+				5311BD571EA7E1A100525281 /* Signals.h */,
 			);
 			path = threads;
 			sourceTree = "<group>";
@@ -1461,6 +1476,7 @@
 				DE5A09FC1BA36992003D4424 /* CommonCryptoSPI.h in Headers */,
 				0F8F2B91172E00FC007DBDA5 /* CompilationThread.h in Headers */,
 				A8A47398151A825B004123FF /* Compiler.h in Headers */,
+				5311BD561EA7E15A00525281 /* LocklessBag.h in Headers */,
 				0FDB698E1B7C643A000C1078 /* Condition.h in Headers */,
 				A8A4748C151A8264004123FF /* config.h in Headers */,
 				0F8F2B9C172F2596007DBDA5 /* ConversionMode.h in Headers */,
@@ -1526,6 +1542,7 @@
 				A70DA0841799F04D00529A9B /* Insertion.h in Headers */,
 				26147B0A15DDCCDC00DDB907 /* IntegerToStringConversion.h in Headers */,
 				7CDD7FF8186D291E007433CD /* IteratorAdaptors.h in Headers */,
+				5311BD581EA7E1A100525281 /* Signals.h in Headers */,
 				7CDD7FFA186D2A54007433CD /* IteratorRange.h in Headers */,
 				93AC91A818942FC400244939 /* LChar.h in Headers */,
 				539EB0631D55284200C82EF7 /* LEBDecoder.h in Headers */,
@@ -1633,6 +1650,7 @@
 				A748745417A0BDAE00FA04CB /* StringHashDumpContext.h in Headers */,
 				A8A47441151A825B004123FF /* StringImpl.h in Headers */,
 				A8A47442151A825B004123FF /* StringOperators.h in Headers */,
+				5311BD5A1EA81A9600525281 /* ThreadMessage.h in Headers */,
 				0FDDBFA81666DFA300C55FEF /* StringPrintStream.h in Headers */,
 				1A6EB1E0187D0BD30030126F /* StringView.h in Headers */,
 				A8A473B8151A825B004123FF /* strtod.h in Headers */,
@@ -1857,8 +1875,10 @@
 				FEDACD3D1630F83F00C69634 /* StackStats.cpp in Sources */,
 				A8A4743C151A825B004123FF /* StringBuilder.cpp in Sources */,
 				A5BA15FB182435A600A82E69 /* StringCF.cpp in Sources */,
+				5311BD5C1EA822F900525281 /* ThreadMessage.cpp in Sources */,
 				A8A47440151A825B004123FF /* StringImpl.cpp in Sources */,
 				A5BA15FC182435A600A82E69 /* StringImplCF.cpp in Sources */,
+				5311BD531EA71CAD00525281 /* Signals.cpp in Sources */,
 				A5BA15F51824348000A82E69 /* StringImplMac.mm in Sources */,
 				A5BA15F3182433A900A82E69 /* StringMac.mm in Sources */,
 				0FDDBFA71666DFA300C55FEF /* StringPrintStream.cpp in Sources */,

Modified: trunk/Source/WTF/wtf/Atomics.h (215637 => 215638)


--- trunk/Source/WTF/wtf/Atomics.h	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/WTF/wtf/Atomics.h	2017-04-21 21:28:17 UTC (rev 215638)
@@ -131,6 +131,12 @@
         return transaction(func, std::memory_order_relaxed);
     }
 
+    Atomic() = default;
+    constexpr Atomic(T initial)
+        : value(std::forward<T>(initial))
+    {
+    }
+
     std::atomic<T> value;
 };
 

Modified: trunk/Source/WTF/wtf/CMakeLists.txt (215637 => 215638)


--- trunk/Source/WTF/wtf/CMakeLists.txt	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/WTF/wtf/CMakeLists.txt	2017-04-21 21:28:17 UTC (rev 215638)
@@ -62,6 +62,7 @@
     LockAlgorithm.h
     LockedPrintStream.h
     Locker.h
+    LocklessBag.h
     LoggingHashID.h
     LoggingHashMap.h
     LoggingHashSet.h
@@ -130,6 +131,7 @@
     StringPrintStream.h
     SystemTracing.h
     ThreadHolder.cpp
+    ThreadMessage.h
     ThreadSafeRefCounted.h
     ThreadSpecific.h
     Threading.h
@@ -185,6 +187,7 @@
     text/icu/UTextProviderUTF16.h
 
     threads/BinarySemaphore.h
+    threads/Signals.h
 
     unicode/CharacterNames.h
     unicode/Collator.h
@@ -239,6 +242,7 @@
     StackBounds.cpp
     StackStats.cpp
     StringPrintStream.cpp
+    ThreadMessage.cpp
     Threading.cpp
     TimeWithDynamicClockType.cpp
     WTFThreadData.cpp
@@ -279,6 +283,7 @@
     text/icu/UTextProviderUTF16.cpp
 
     threads/BinarySemaphore.cpp
+    threads/Signals.cpp
 
     unicode/UTF8.cpp
 )

Added: trunk/Source/WTF/wtf/LocklessBag.h (0 => 215638)


--- trunk/Source/WTF/wtf/LocklessBag.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/LocklessBag.h	2017-04-21 21:28:17 UTC (rev 215638)
@@ -0,0 +1,97 @@
+/*
+ * 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. ``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
+ * 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.
+ */
+
+#pragma once
+
+#include "Atomics.h"
+
+namespace WTF {
+
+// This a simple single consumer, multiple producer Bag data structure.
+
+template<typename T>
+class LocklessBag {
+    WTF_MAKE_NONCOPYABLE(LocklessBag);
+
+    struct Node {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        T data;
+        Node* next;
+    };
+public:
+    LocklessBag()
+        : m_head(nullptr)
+    {
+    }
+
+    enum PushResult { Empty, NonEmpty };
+    PushResult add(T&& element)
+    {
+        Node* newNode = new Node();
+        newNode->data = ""
+
+        Node* oldHead;
+        m_head.transaction([&] (Node*& head) {
+            oldHead = head;
+            newNode->next = head;
+            head = newNode;
+            return true;
+        });
+
+        return oldHead == nullptr ? Empty : NonEmpty;
+    }
+
+    // CONSUMER FUNCTIONS: Everything below here is only safe to call from the consumer thread.
+
+    // This function is actually safe to call from more than one thread, but ONLY if no thread can call consumeAll.
+    template<typename Functor>
+    void iterate(const Functor& func)
+    {
+        Node* node = m_head.load();
+        while (node) {
+            const T& data = ""
+            func(data);
+            node = node->next;
+        }
+    }
+
+    template<typename Functor>
+    void consumeAll(const Functor& func)
+    {
+        Node* node = m_head.exchange(nullptr);
+        while (node) {
+            func(WTFMove(node->data));
+            Node* oldNode = node;
+            node = node->next;
+            delete oldNode;
+        }
+    }
+
+private:
+    Atomic<Node*> m_head;
+};
+    
+} // namespace WTF

Added: trunk/Source/WTF/wtf/ThreadMessage.cpp (0 => 215638)


--- trunk/Source/WTF/wtf/ThreadMessage.cpp	                        (rev 0)
+++ trunk/Source/WTF/wtf/ThreadMessage.cpp	2017-04-21 21:28:17 UTC (rev 215638)
@@ -0,0 +1,154 @@
+/*
+ * 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. ``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
+ * 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.
+ */
+
+#include "config.h"
+#include "ThreadMessage.h"
+
+#if USE(PTHREADS)
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <wtf/DataLog.h>
+#include <wtf/Lock.h>
+#include <wtf/Locker.h>
+#include <wtf/threads/Signals.h>
+
+
+namespace WTF {
+
+class ThreadMessageData {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ThreadMessageData(const ThreadMessage& m)
+        : ran(false)
+        , message(m)
+    {
+    }
+
+    Atomic<bool> ran;
+    const ThreadMessage& message;
+};
+
+enum FileDescriptor {
+    Read,
+    Write,
+    NumberOfFileDescriptors,
+};
+
+static int fileDescriptors[NumberOfFileDescriptors];
+static const char* const magicByte = "d";
+
+
+void initializeThreadMessages()
+{
+    int result = pipe(fileDescriptors);
+    RELEASE_ASSERT(!result);
+
+    int flags = fcntl(fileDescriptors[Write], F_GETFL);
+    result = fcntl(fileDescriptors[Write], F_SETFL, flags | O_NONBLOCK | O_APPEND);
+    flags = fcntl(fileDescriptors[Write], F_GETFL);
+    RELEASE_ASSERT(result != -1);
+    RELEASE_ASSERT((flags & O_NONBLOCK) && (flags & O_APPEND));
+
+    flags = fcntl(fileDescriptors[Read], F_GETFL);
+    result = fcntl(fileDescriptors[Read], F_SETFL, flags & ~O_NONBLOCK);
+    flags = fcntl(fileDescriptors[Read], F_GETFL);
+    RELEASE_ASSERT(result != -1);
+    RELEASE_ASSERT(!(flags & O_NONBLOCK));
+}
+
+SUPPRESS_ASAN
+MessageStatus sendMessageScoped(Thread& thread, const ThreadMessage& message)
+{
+    constexpr Signal signal = Signal::Usr;
+    static std::once_flag once;
+    std::call_once(once, [] {
+        installSignalHandler(signal, [] (int, siginfo_t* info, void* uap) {
+            Thread* thread = Thread::currentMayBeNull();
+
+            if (!thread) {
+                dataLogLn("We somehow got a message on a thread that didn't have a WTF::Thread initialized, we probably deadlocked, halp.");
+                return SignalAction::NotHandled;
+            }
+
+            thread->threadMessages().consumeAll([&] (ThreadMessageData* data) {
+                data->message(info, static_cast<ucontext_t*>(uap));
+                data->ran.store(true);
+            });
+
+            while (write(fileDescriptors[Write], magicByte, 1) == -1)
+                ASSERT(errno == EAGAIN);
+
+            return SignalAction::Handled;
+        });
+    });
+
+
+    // Since we are guarenteed not to return until we get a response from the other thread this is ok.
+    ThreadMessageData data(message);
+
+    thread.threadMessages().add(&data);
+    bool result = thread.signal(toSystemSignal(signal));
+    if (!result)
+        return MessageStatus::ThreadExited;
+    RELEASE_ASSERT(result);
+
+    static StaticLock readLock;
+    while (true) {
+        LockHolder locker(readLock);
+        constexpr size_t bufferSize = 16;
+        char buffer[bufferSize];
+
+        // It's always safe to clear the pipe because only one thread can ever block trying to read
+        // from the pipe. Thus, each byte we clear from the pipe actually just corresponds to some task
+        // that has already finished. We actively want to ensure that the pipe does not overfill because
+        // otherwise our writers might spin trying to write.
+        auto clearPipe = [&] {
+            int flags = fcntl(fileDescriptors[Read], F_GETFL);
+            ASSERT(!(flags & O_NONBLOCK));
+            fcntl(fileDescriptors[Read], F_SETFL, flags | O_NONBLOCK);
+
+            while (read(fileDescriptors[Read], buffer, bufferSize) != -1) { }
+            ASSERT(errno == EAGAIN);
+
+            fcntl(fileDescriptors[Read], F_SETFL, flags);
+        };
+
+        if (data.ran.load()) {
+            clearPipe();
+            return MessageStatus::MessageRan;
+        }
+
+        read(fileDescriptors[Read], buffer, 1);
+        ASSERT(buffer[0] == magicByte[0]);
+        clearPipe();
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
+#endif // USE(PTHREADS)

Added: trunk/Source/WTF/wtf/ThreadMessage.h (0 => 215638)


--- trunk/Source/WTF/wtf/ThreadMessage.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/ThreadMessage.h	2017-04-21 21:28:17 UTC (rev 215638)
@@ -0,0 +1,62 @@
+/*
+ * 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. ``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
+ * 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.
+ */
+
+#pragma once
+
+#include <wtf/Ref.h>
+#include <wtf/ScopedLambda.h>
+#include <wtf/Threading.h>
+
+#if USE(PTHREADS)
+
+namespace WTF {
+
+void initializeThreadMessages();
+
+class ThreadMessageData;
+using ThreadMessage = ScopedLambda<void(siginfo_t*, ucontext_t*)>;
+
+enum class MessageStatus {
+    MessageRan,
+    ThreadExited,
+};
+
+// This method allows us to send a message which will be run in a signal handler on the desired thread.
+// There are several caveates to this method however, This function uses signals so your message should
+// be sync signal safe.
+MessageStatus sendMessageScoped(Thread&, const ThreadMessage&);
+
+template<typename Functor>
+MessageStatus sendMessage(Thread& targetThread, const Functor& func)
+{
+    auto lambda = scopedLambdaRef<void(siginfo_t*, ucontext_t*)>(func);
+    return sendMessageScoped(targetThread, lambda);
+}
+
+} // namespace WTF
+
+using WTF::sendMessage;
+
+#endif // USE(PTHREADS)

Modified: trunk/Source/WTF/wtf/Threading.cpp (215637 => 215638)


--- trunk/Source/WTF/wtf/Threading.cpp	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/WTF/wtf/Threading.cpp	2017-04-21 21:28:17 UTC (rev 215638)
@@ -34,6 +34,7 @@
 #include <wtf/DateMath.h>
 #include <wtf/RandomNumberSeed.h>
 #include <wtf/ThreadHolder.h>
+#include <wtf/ThreadMessage.h>
 #include <wtf/WTFThreadData.h>
 #include <wtf/text/StringView.h>
 
@@ -178,6 +179,9 @@
         wtfThreadData();
         initializeDates();
         Thread::initializePlatformThreading();
+#if USE(PTHREADS)
+        initializeThreadMessages();
+#endif
     });
 }
 

Modified: trunk/Source/WTF/wtf/Threading.h (215637 => 215638)


--- trunk/Source/WTF/wtf/Threading.h	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/WTF/wtf/Threading.h	2017-04-21 21:28:17 UTC (rev 215638)
@@ -42,6 +42,7 @@
 #include <wtf/Atomics.h>
 #include <wtf/Expected.h>
 #include <wtf/Locker.h>
+#include <wtf/LocklessBag.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/PlatformRegisters.h>
 #include <wtf/PrintStream.h>
@@ -56,6 +57,8 @@
 
 namespace WTF {
 
+class ThreadMessageData;
+
 using ThreadIdentifier = uint32_t;
 typedef void (*ThreadFunction)(void* argument);
 
@@ -75,6 +78,7 @@
 
     // Returns Thread object.
     WTF_EXPORT_PRIVATE static Thread& current();
+    WTF_EXPORT_PRIVATE static Thread* currentMayBeNull();
 
     // Returns ThreadIdentifier directly. It is useful if the user only cares about identity
     // of threads. At that time, users should know that holding this ThreadIdentifier does not ensure
@@ -132,7 +136,11 @@
 
     static void initializePlatformThreading();
 
-private:
+#if USE(PTHREADS)
+    LocklessBag<ThreadMessageData*>& threadMessages() { return m_threadMessages; }
+#endif
+
+protected:
     Thread();
 
     // Internal platform-specific Thread::create implementation.
@@ -177,6 +185,8 @@
     bool m_didExit { false };
 #if USE(PTHREADS)
     pthread_t m_handle;
+
+    LocklessBag<ThreadMessageData*> m_threadMessages;
 #if OS(DARWIN)
     mach_port_t m_platformThread;
 #else

Modified: trunk/Source/WTF/wtf/ThreadingPthreads.cpp (215637 => 215638)


--- trunk/Source/WTF/wtf/ThreadingPthreads.cpp	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Source/WTF/wtf/ThreadingPthreads.cpp	2017-04-21 21:28:17 UTC (rev 215638)
@@ -264,12 +264,19 @@
         didBecomeDetached();
 }
 
-Thread& Thread::current()
+Thread* Thread::currentMayBeNull()
 {
     ThreadHolder* data = ""
     if (data)
-        return data->thread();
+        return &data->thread();
+    return nullptr;
+}
 
+Thread& Thread::current()
+{
+    if (Thread* current = currentMayBeNull())
+        return *current;
+
     // Not a WTF-created thread, ThreadIdentifier is not established yet.
     RefPtr<Thread> thread = adoptRef(new Thread());
     thread->establish(pthread_self());
@@ -286,6 +293,8 @@
 bool Thread::signal(int signalNumber)
 {
     std::unique_lock<std::mutex> locker(m_mutex);
+    if (hasExited())
+        return false;
     int errNo = pthread_kill(m_handle, signalNumber);
     return !errNo; // A 0 errNo means success.
 }

Added: trunk/Source/WTF/wtf/threads/Signals.cpp (0 => 215638)


--- trunk/Source/WTF/wtf/threads/Signals.cpp	                        (rev 0)
+++ trunk/Source/WTF/wtf/threads/Signals.cpp	2017-04-21 21:28:17 UTC (rev 215638)
@@ -0,0 +1,119 @@
+/*
+ * 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. ``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
+ * 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.
+ */
+
+#include "config.h"
+#include "Signals.h"
+
+#if USE(PTHREADS)
+
+#include <mutex>
+#include <signal.h>
+#include <wtf/Atomics.h>
+#include <wtf/DataLog.h>
+#include <wtf/LocklessBag.h>
+
+namespace WTF {
+
+static LocklessBag<SignalHandler> handlers[static_cast<size_t>(Signal::NumberOfSignals)] = { };
+static struct sigaction oldActions[static_cast<size_t>(Signal::NumberOfSignals)];
+static std::once_flag initializeOnceFlags[static_cast<size_t>(Signal::NumberOfSignals)];
+
+static void jscSignalHandler(int sig, siginfo_t* info, void* mcontext)
+{
+    Signal signal = fromSystemSignal(sig);
+
+    auto restoreDefault = [&] {
+        struct sigaction defaultAction;
+        defaultAction.sa_handler = SIG_DFL;
+        sigfillset(&defaultAction.sa_mask);
+        defaultAction.sa_flags = 0;
+        auto result = sigaction(sig, &defaultAction, nullptr);
+        dataLogLnIf(!result, "Unable to restore the default handler while proccessing signal ", sig, " the process is probably deadlocked.");
+    };
+
+    // This shouldn't happen but we might as well be careful.
+    if (signal == Signal::Unknown) {
+        dataLogLn("We somehow got called for an unknown signal ", sig, ", halp.");
+        restoreDefault();
+        return;
+    }
+
+    bool didHandle = false;
+    bool restoreDefaultHandler = false;
+    handlers[static_cast<size_t>(signal)].iterate([&] (const SignalHandler& handler) {
+        switch (handler(sig, info, mcontext)) {
+        case SignalAction::Handled:
+            didHandle = true;
+            break;
+        case SignalAction::ForceDefault:
+            restoreDefaultHandler = true;
+            break;
+        default:
+            break;
+        }
+    });
+
+    if (restoreDefaultHandler) {
+        restoreDefault();
+        return;
+    }
+
+    struct sigaction& oldAction = oldActions[static_cast<size_t>(signal)];
+    if (signal == Signal::Usr) {
+        if (oldAction.sa_sigaction)
+            oldAction.sa_sigaction(sig, info, mcontext);
+        return;
+    }
+
+    if (!didHandle) {
+        if (oldAction.sa_sigaction) {
+            oldAction.sa_sigaction(sig, info, mcontext);
+            return;
+        }
+
+        restoreDefault();
+        return;
+    }
+}
+
+void installSignalHandler(Signal signal, SignalHandler&& handler)
+{
+    ASSERT(signal < Signal::Unknown);
+    handlers[static_cast<size_t>(signal)].add(WTFMove(handler));
+
+    std::call_once(initializeOnceFlags[static_cast<size_t>(signal)], [&] {
+        struct sigaction action;
+        action.sa_sigaction = jscSignalHandler;
+        auto result = sigfillset(&action.sa_mask);
+        RELEASE_ASSERT(!result);
+        action.sa_flags = SA_SIGINFO;
+        result = sigaction(toSystemSignal(signal), &action, &oldActions[static_cast<size_t>(signal)]);
+        RELEASE_ASSERT(!result);
+    });
+}
+
+} // namespace WTF
+
+#endif // USE(PTHREADS)

Added: trunk/Source/WTF/wtf/threads/Signals.h (0 => 215638)


--- trunk/Source/WTF/wtf/threads/Signals.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/threads/Signals.h	2017-04-21 21:28:17 UTC (rev 215638)
@@ -0,0 +1,97 @@
+/*
+ * 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. ``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
+ * 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.
+ */
+
+#pragma once
+
+#if USE(PTHREADS)
+
+#include <signal.h>
+#include <wtf/Function.h>
+
+namespace WTF {
+
+enum class Signal {
+    // Usr will always chain to any non-default handler install before us. Since there is no way to know
+    // if a signal was intended exclusively for us.
+    Usr,
+
+    // These signals will only chain if we don't have a handler that can process them. If there is nothing
+    // to chain to we restore the default handler and crash.
+    Trap,
+    Ill,
+    SegV,
+    Bus,
+    NumberOfSignals,
+    Unknown = NumberOfSignals
+};
+
+inline int toSystemSignal(Signal signal)
+{
+    switch (signal) {
+    case Signal::SegV: return SIGSEGV;
+    case Signal::Bus: return SIGBUS;
+    case Signal::Ill: return SIGILL;
+    case Signal::Usr: return SIGUSR2;
+    case Signal::Trap: return SIGTRAP;
+    default: break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+inline Signal fromSystemSignal(int signal)
+{
+    switch (signal) {
+    case SIGSEGV: return Signal::SegV;
+    case SIGBUS: return Signal::Bus;
+    case SIGILL: return Signal::Ill;
+    case SIGUSR2: return Signal::Usr;
+    case SIGTRAP: return Signal::Trap;
+    default: return Signal::Unknown;
+    }
+}
+
+enum class SignalAction {
+    Handled,
+    NotHandled,
+    ForceDefault
+};
+
+using SignalHandler = Function<SignalAction(int, siginfo_t*, void*)>;
+
+// Call this method whenever you want to install a signal handler. It's ok to call this function lazily.
+// Note: Your signal handler will be called every time the handler for the desired signal is called.
+// Thus it is your responsibility to discern if the signal fired was yours.
+// This function is currently a one way street i.e. once installed, a signal handler cannot be uninstalled.
+void installSignalHandler(Signal, SignalHandler&&);
+
+} // namespace WTF
+
+using WTF::Signal;
+using WTF::toSystemSignal;
+using WTF::fromSystemSignal;
+using WTF::SignalAction;
+using WTF::installSignalHandler;
+
+#endif // USE(PTHREADS)

Modified: trunk/Tools/ChangeLog (215637 => 215638)


--- trunk/Tools/ChangeLog	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Tools/ChangeLog	2017-04-21 21:28:17 UTC (rev 215638)
@@ -1,3 +1,15 @@
+2017-04-21  Keith Miller  <[email protected]>
+
+        Unreviewed, rolling out r215634.
+
+        underlying build issues should have been fixed
+
+        Reverted changeset:
+
+        "Unreviewed, rolling out r215620 and r215623."
+        https://bugs.webkit.org/show_bug.cgi?id=171139
+        http://trac.webkit.org/changeset/215634
+
 2017-04-21  Aakash Jain  <[email protected]>
 
         Bubbles on dashboard doesn't turn red for test262 failures

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (215637 => 215638)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-04-21 21:14:15 UTC (rev 215637)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-04-21 21:28:17 UTC (rev 215638)
@@ -174,6 +174,7 @@
 		52B8CF9815868D9100281053 /* SetDocumentURI.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 52B8CF9415868CF000281053 /* SetDocumentURI.html */; };
 		52D673EE1AFB127300FA19FE /* WKPageCopySessionStateWithFiltering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52D673EC1AFB126800FA19FE /* WKPageCopySessionStateWithFiltering.cpp */; };
 		52E5CE4914D21EAB003B2BD8 /* ParentFrame_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52E5CE4814D21EAB003B2BD8 /* ParentFrame_Bundle.cpp */; };
+		5311BD5E1EA9490E00525281 /* ThreadMessages.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5311BD5D1EA9490D00525281 /* ThreadMessages.cpp */; };
 		531C1D8E1DF8EF72006E979F /* LEBDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531C1D8D1DF8EF72006E979F /* LEBDecoder.cpp */; };
 		536770341CC8022800D425B1 /* WebScriptObjectDescription.mm in Sources */ = {isa = PBXBuildFile; fileRef = 536770331CC8022800D425B1 /* WebScriptObjectDescription.mm */; };
 		536770361CC81B6100D425B1 /* WebScriptObjectDescription.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 536770351CC812F900D425B1 /* WebScriptObjectDescription.html */; };
@@ -1116,6 +1117,7 @@
 		52D673EC1AFB126800FA19FE /* WKPageCopySessionStateWithFiltering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKPageCopySessionStateWithFiltering.cpp; sourceTree = "<group>"; };
 		52E5CE4514D21E9D003B2BD8 /* ParentFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParentFrame.cpp; sourceTree = "<group>"; };
 		52E5CE4814D21EAB003B2BD8 /* ParentFrame_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParentFrame_Bundle.cpp; sourceTree = "<group>"; };
+		5311BD5D1EA9490D00525281 /* ThreadMessages.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadMessages.cpp; sourceTree = "<group>"; };
 		531C1D8D1DF8EF72006E979F /* LEBDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LEBDecoder.cpp; sourceTree = "<group>"; };
 		536770331CC8022800D425B1 /* WebScriptObjectDescription.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebScriptObjectDescription.mm; sourceTree = "<group>"; };
 		536770351CC812F900D425B1 /* WebScriptObjectDescription.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = WebScriptObjectDescription.html; sourceTree = "<group>"; };
@@ -2177,6 +2179,7 @@
 				7C74D42D188228F300E5ED57 /* StringView.cpp */,
 				5597F8341D9596C80066BC21 /* SynchronizedFixedQueue.cpp */,
 				9329AA281DE3F81E003ABD07 /* TextBreakIterator.cpp */,
+				5311BD5D1EA9490D00525281 /* ThreadMessages.cpp */,
 				0F2C20B71DCD544800542D9E /* Time.cpp */,
 				5C5E633D1D0B67940085A025 /* UniqueRef.cpp */,
 				7CD0D5AA1D5534DE000CC9E1 /* Variant.cpp */,
@@ -2697,6 +2700,7 @@
 				7C83DEE01D0A590C00FEBCF3 /* IntegerToStringConversion.cpp in Sources */,
 				531C1D8E1DF8EF72006E979F /* LEBDecoder.cpp in Sources */,
 				7C83DEE81D0A590C00FEBCF3 /* ListHashSet.cpp in Sources */,
+				5311BD5E1EA9490E00525281 /* ThreadMessages.cpp in Sources */,
 				7C83DF1D1D0A590C00FEBCF3 /* Lock.cpp in Sources */,
 				7C83DEED1D0A590C00FEBCF3 /* MathExtras.cpp in Sources */,
 				7C83DEEF1D0A590C00FEBCF3 /* MD5.cpp in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WTF/ThreadMessages.cpp (0 => 215638)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/ThreadMessages.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/ThreadMessages.cpp	2017-04-21 21:28:17 UTC (rev 215638)
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include <type_traits>
+#include <wtf/DataLog.h>
+#include <wtf/HashSet.h>
+#include <wtf/Ref.h>
+#include <wtf/ThreadMessage.h>
+#include <wtf/Vector.h>
+#include <wtf/threads/Signals.h>
+
+static void runThreadMessageTest(unsigned numSenders, unsigned numMessages)
+{
+    bool receiverShouldKeepRunning = true;
+    dataLogLn("starting");
+    RefPtr<Thread> receiverThread = Thread::create("ThreadMessage receiver", [&receiverShouldKeepRunning] () {
+        while (receiverShouldKeepRunning) { }
+    });
+    ASSERT_TRUE(receiverThread);
+
+    Vector<RefPtr<Thread>> senderThreads(numSenders);
+    Vector<unsigned> messagesRun(numSenders);
+    Vector<unsigned> handlersRun(numSenders);
+    messagesRun.fill(0);
+    handlersRun.fill(0);
+
+    for (unsigned senderID = 0; senderID < numSenders; ++senderID) {
+        senderThreads[senderID] = Thread::create("ThreadMessage sender", [senderID, numMessages, receiverThread, &messagesRun, &handlersRun] () {
+            for (unsigned i = 0; i < numMessages; ++i) {
+                auto result = sendMessage(*receiverThread.get(), [senderID, &handlersRun] (siginfo_t*, ucontext_t*) {
+                    handlersRun[senderID]++;
+                });
+                EXPECT_TRUE(result == WTF::MessageStatus::MessageRan);
+                messagesRun[senderID]++;
+            }
+        });
+        ASSERT_TRUE(senderThreads[senderID]);
+    }
+
+    for (unsigned i = 0; i < numSenders; ++i)
+        senderThreads[i]->waitForCompletion();
+
+    receiverShouldKeepRunning = false;
+    receiverThread->waitForCompletion();
+
+    for (unsigned i = 0; i < numSenders; ++i) {
+        EXPECT_EQ(numMessages, messagesRun[i]);
+        EXPECT_EQ(numMessages, handlersRun[i]);
+    }
+}
+
+TEST(ThreadMessage, Basic)
+{
+    runThreadMessageTest(1, 1);
+    runThreadMessageTest(1, 100);
+}
+
+TEST(ThreadMessage, MultipleSenders)
+{
+    runThreadMessageTest(10, 1);
+    runThreadMessageTest(10, 100);
+    runThreadMessageTest(10, 10000);
+}
+
+class ReflectedThread : public Thread {
+public:
+    using Thread::m_mutex;
+    using Thread::m_handle;
+    using Thread::hasExited;
+};
+
+TEST(ThreadMessage, SignalsWorkOnExit)
+{
+    static bool handlerRan = false;
+    installSignalHandler(Signal::Usr, [] (int, siginfo_t*, void*) -> SignalAction {
+        dataLogLn("here");
+        handlerRan = true;
+        return SignalAction::Handled;
+    });
+
+    bool receiverShouldKeepRunning = true;
+    RefPtr<Thread> receiverThread = (Thread::create("ThreadMessage receiver",
+        [&receiverShouldKeepRunning] () {
+            while (receiverShouldKeepRunning) { }
+    }));
+    ASSERT_TRUE(receiverThread);
+
+    bool signalFired;
+    {
+        std::unique_lock<std::mutex> locker(static_cast<ReflectedThread*>(receiverThread.get())->m_mutex);
+        receiverShouldKeepRunning = false;
+        EXPECT_FALSE(static_cast<ReflectedThread*>(receiverThread.get())->hasExited());
+        sleep(1);
+        signalFired = !pthread_kill(static_cast<ReflectedThread*>(receiverThread.get())->m_handle, toSystemSignal(Signal::Usr));
+    }
+
+    receiverThread->waitForCompletion();
+    EXPECT_TRUE(handlerRan || !signalFired);
+}
+
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to