Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Source/JavaScriptCore/wasm/WasmFaultSignalHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
#include "config.h"
#include "WasmFaultSignalHandler.h"

// FIXME: https://bugs.webkit.org/show_bug.cgi?id=259108 Support signal handlers on Windows
#if ENABLE(WEBASSEMBLY) && OS(UNIX)
#if ENABLE(WEBASSEMBLY)

#include "ExecutableAllocator.h"
#include "LLIntData.h"
Expand Down Expand Up @@ -133,5 +132,5 @@ void prepareSignalingMemory()

} } // namespace JSC::Wasm

#endif // ENABLE(WEBASSEMBLY) && OS(UNIX)
#endif // ENABLE(WEBASSEMBLY)

2 changes: 1 addition & 1 deletion Source/JavaScriptCore/wasm/WasmFaultSignalHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace JSC {

namespace Wasm {

#if ENABLE(WEBASSEMBLY) && OS(UNIX)
#if ENABLE(WEBASSEMBLY)
void activateSignalingMemory();
void prepareSignalingMemory();
#else
Expand Down
1 change: 1 addition & 0 deletions Source/WTF/wtf/PlatformJSCOnly.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ if (WIN32)
win/MainThreadWin.cpp
win/OSAllocatorWin.cpp
win/PathWalker.cpp
win/SignalsWin.cpp
win/ThreadingWin.cpp
)
list(APPEND WTF_PUBLIC_HEADERS
Expand Down
1 change: 1 addition & 0 deletions Source/WTF/wtf/PlatformWin.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ list(APPEND WTF_SOURCES
win/OSAllocatorWin.cpp
win/PathWalker.cpp
win/RunLoopWin.cpp
win/SignalsWin.cpp
win/ThreadingWin.cpp
win/Win32Handle.cpp
)
Expand Down
2 changes: 0 additions & 2 deletions Source/WTF/wtf/WTFConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,7 @@ struct Config {
bool isThreadSuspendResumeSignalConfigured;
int sigThreadSuspendResume;
#endif
#if OS(UNIX)
SignalHandlers signalHandlers;
#endif
PtrTagLookup* ptrTagLookupHead;

uint64_t spaceForExtensions[1];
Expand Down
33 changes: 32 additions & 1 deletion Source/WTF/wtf/threads/Signals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include "config.h"
#include <wtf/threads/Signals.h>

// FIXME: https://bugs.webkit.org/show_bug.cgi?id=259108 Support signal handlers on Windows
#if OS(UNIX)

#if HAVE(MACH_EXCEPTIONS)
Expand Down Expand Up @@ -336,6 +335,38 @@ void registerThreadForMachExceptionHandling(Thread& thread)

#endif // HAVE(MACH_EXCEPTIONS)

inline std::tuple<int, std::optional<int>> toSystemSignal(Signal signal)
{
switch (signal) {
case Signal::AccessFault: return std::make_tuple(SIGSEGV, SIGBUS);
case Signal::IllegalInstruction: return std::make_tuple(SIGILL, std::nullopt);
case Signal::Usr: return std::make_tuple(SIGUSR2, std::nullopt);
case Signal::FloatingPoint: return std::make_tuple(SIGFPE, std::nullopt);
case Signal::Breakpoint: return std::make_tuple(SIGTRAP, std::nullopt);
#if !OS(DARWIN)
case Signal::Abort: return std::make_tuple(SIGABRT, std::nullopt);
#endif
default: break;
}
RELEASE_ASSERT_NOT_REACHED();
}

inline Signal fromSystemSignal(int signal)
{
switch (signal) {
case SIGSEGV: return Signal::AccessFault;
case SIGBUS: return Signal::AccessFault;
case SIGFPE: return Signal::FloatingPoint;
case SIGTRAP: return Signal::Breakpoint;
case SIGILL: return Signal::IllegalInstruction;
case SIGUSR2: return Signal::Usr;
#if !OS(DARWIN)
case SIGABRT: return Signal::Abort;
#endif
default: return Signal::Unknown;
}
}

Comment on lines +338 to +369
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put this at the top of the block and the build should go back to green.

inline size_t offsetForSystemSignal(int sig)
{
Signal signal = fromSystemSignal(sig);
Expand Down
65 changes: 16 additions & 49 deletions Source/WTF/wtf/threads/Signals.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,25 @@

#pragma once

#include <wtf/Function.h>
#include <wtf/Lock.h>
#include <wtf/PlatformRegisters.h>

#if OS(UNIX)

#include <signal.h>
#include <tuple>
#include <wtf/Function.h>
#include <wtf/Lock.h>
#include <wtf/PlatformRegisters.h>

#if HAVE(MACH_EXCEPTIONS)
#include <mach/exception_types.h>
#endif
#endif // OS(UNIX)

namespace WTF {

// Note that SIGUSR1 is used in Pthread-based ports except for Darwin to suspend and resume threads.
enum class Signal {
#if OS(UNIX)
// 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,
Expand All @@ -56,39 +59,14 @@ enum class Signal {
AccessFault, // For posix this is both SIGSEGV and SIGBUS
NumberOfSignals = AccessFault + 2, // AccessFault is really two signals.
Unknown = NumberOfSignals
};

inline std::tuple<int, std::optional<int>> toSystemSignal(Signal signal)
{
switch (signal) {
case Signal::AccessFault: return std::make_tuple(SIGSEGV, SIGBUS);
case Signal::IllegalInstruction: return std::make_tuple(SIGILL, std::nullopt);
case Signal::Usr: return std::make_tuple(SIGUSR2, std::nullopt);
case Signal::FloatingPoint: return std::make_tuple(SIGFPE, std::nullopt);
case Signal::Breakpoint: return std::make_tuple(SIGTRAP, std::nullopt);
#if !OS(DARWIN)
case Signal::Abort: return std::make_tuple(SIGABRT, std::nullopt);
#endif
default: break;
}
RELEASE_ASSERT_NOT_REACHED();
}

inline Signal fromSystemSignal(int signal)
{
switch (signal) {
case SIGSEGV: return Signal::AccessFault;
case SIGBUS: return Signal::AccessFault;
case SIGFPE: return Signal::FloatingPoint;
case SIGTRAP: return Signal::Breakpoint;
case SIGILL: return Signal::IllegalInstruction;
case SIGUSR2: return Signal::Usr;
#if !OS(DARWIN)
case SIGABRT: return Signal::Abort;
#else
FloatingPoint,
IllegalInstruction,
AccessFault,
NumberOfSignals = AccessFault + 1,
Unknown = NumberOfSignals
#endif
default: return Signal::Unknown;
}
}
};

enum class SignalAction {
Handled,
Expand Down Expand Up @@ -131,7 +109,10 @@ struct SignalHandlers {
#endif
uint8_t numberOfHandlers[numberOfSignals];
SignalHandlerMemory handlers[numberOfSignals][maxNumberOfHandlers];

#if OS(UNIX)
struct sigaction oldActions[numberOfSignals];
#endif
};

// Call this method whenever you want to add a signal handler. This function needs to be called
Expand Down Expand Up @@ -167,23 +148,9 @@ using WTF::handleSignalsWithMach;

using WTF::Signal;
using WTF::SigInfo;
using WTF::toSystemSignal;
using WTF::fromSystemSignal;
using WTF::SignalAction;
using WTF::SignalHandler;
using WTF::addSignalHandler;
using WTF::activateSignalHandlersFor;

#else // not OS(UNIX)

namespace WTF {

inline void initializeSignalHandling() { }
inline void disableSignalHandling() { }

} // namespace WTF

#endif // OS(UNIX)

using WTF::initializeSignalHandling;
using WTF::disableSignalHandling;
154 changes: 154 additions & 0 deletions Source/WTF/wtf/win/SignalsWin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* Copyright (C) 2023 Ian Grunert <ian.grunert@gmail.com>
*
* 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 <wtf/threads/Signals.h>

#if OS(WINDOWS)

#include <cstdio>
#include <mutex>
#include <signal.h>
#include <winnt.h>

#include <wtf/Atomics.h>
#include <wtf/DataLog.h>
#include <wtf/MathExtras.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/PlatformRegisters.h>
#include <wtf/ThreadGroup.h>
#include <wtf/Threading.h>
#include <wtf/WTFConfig.h>

namespace WTF {

void SignalHandlers::add(Signal signal, SignalHandler&& handler)
{
Config::AssertNotFrozenScope assertScope;
static Lock lock;
Locker locker { lock };

size_t signalIndex = static_cast<size_t>(signal);
size_t nextFree = numberOfHandlers[signalIndex];
RELEASE_ASSERT(nextFree < maxNumberOfHandlers);
SignalHandlerMemory* memory = &handlers[signalIndex][nextFree];
new (memory) SignalHandler(WTFMove(handler));

// We deliberately do not want to increment the count until after we've
// fully initialized the memory. This way, forEachHandler() won't see a
// partially initialized handler.
storeStoreFence();
numberOfHandlers[signalIndex]++;
loadLoadFence();
}

template<typename Func>
inline void SignalHandlers::forEachHandler(Signal signal, const Func& func) const
{
size_t signalIndex = static_cast<size_t>(signal);
size_t handlerIndex = numberOfHandlers[signalIndex];
while (handlerIndex--) {
auto* memory = const_cast<SignalHandlerMemory*>(&handlers[signalIndex][handlerIndex]);
const SignalHandler& handler = *bitwise_cast<SignalHandler*>(memory);
func(handler);
}
}

inline Signal fromSystemException(int signal)
{
switch (signal) {
case EXCEPTION_FLT_DENORMAL_OPERAND:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_INEXACT_RESULT:
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_STACK_CHECK:
case EXCEPTION_FLT_UNDERFLOW:
return Signal::FloatingPoint;
case EXCEPTION_ILLEGAL_INSTRUCTION:
return Signal::IllegalInstruction;
case EXCEPTION_ACCESS_VIOLATION:
return Signal::AccessFault;
default:
return Signal::Unknown;
}
}

LONG WINAPI vectoredHandler(struct _EXCEPTION_POINTERS *exceptionInfo)
{
Signal signal = fromSystemException(exceptionInfo->ExceptionRecord->ExceptionCode);
SignalHandlers& handlers = g_wtfConfig.signalHandlers;

SigInfo sigInfo;
if (signal == Signal::AccessFault) {
// The second array element specifies the virtual address of the inaccessible data.
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record
sigInfo.faultingAddress = reinterpret_cast<void*>(exceptionInfo->ExceptionRecord->ExceptionInformation[1]);
}

PlatformRegisters& registers = *(exceptionInfo->ContextRecord);

long result = EXCEPTION_EXECUTE_HANDLER;
handlers.forEachHandler(signal, [&] (const SignalHandler& handler) {
switch (handler(signal, sigInfo, registers)) {
case SignalAction::Handled:
result = EXCEPTION_CONTINUE_EXECUTION;
break;
default:
break;
}
});

return result;
}

void addSignalHandler(Signal signal, SignalHandler&& handler)
{
Config::AssertNotFrozenScope assertScope;
SignalHandlers& handlers = g_wtfConfig.signalHandlers;
ASSERT(signal < Signal::Unknown);

static std::once_flag initializeOnceFlags[static_cast<size_t>(Signal::NumberOfSignals)];
std::call_once(initializeOnceFlags[static_cast<size_t>(signal)], [&] {
Config::AssertNotFrozenScope assertScope;
AddVectoredExceptionHandler(1, vectoredHandler);
});

handlers.add(signal, WTFMove(handler));
}

void activateSignalHandlersFor(Signal signal)
{
UNUSED_PARAM(signal);
}

void SignalHandlers::initialize()
{
// noop
}

} // namespace WTF

#endif // OS(WINDOWS)
1 change: 1 addition & 0 deletions Tools/TestWebKitAPI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ set(TestWTF_SOURCES
Tests/WTF/ScopedLambda.cpp
Tests/WTF/SentinelLinkedList.cpp
Tests/WTF/SetForScope.cpp
Tests/WTF/Signals.cpp
Tests/WTF/StackTraceTest.cpp
Tests/WTF/StdLibExtrasTests.cpp
Tests/WTF/StringBuilder.cpp
Expand Down
Loading