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, ¤tAction);
-
- 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, ¤tAction, 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, ¤tAction);
-
- 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, ¤tAction, 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);
+}
+