Merge DeferredSignalMutex.h and ScopedSignalMask.h into a single file

Using a single file makes sense now that the individual files are much
shorter and share common utility classes.
This commit is contained in:
Tony Wasserka committed 2023-11-17 10:56:34 +01:00
1 parent 5ca35bf77c
commit 92e4e75217
7 files changed
+35 -77

No files matched your search

+1 -1
View File
@@ -14,8 +14,8 @@
#include <FEXCore/Core/SignalDelegator.h>
#include <FEXCore/Debug/InternalThreadState.h>
#include <FEXCore/Utils/CompilerDefs.h>
#include <FEXCore/Utils/DeferredSignalMutex.h>
#include <FEXCore/Utils/Event.h>
#include <FEXCore/Utils/SignalScopeGuards.h>
#include <FEXCore/fextl/memory.h>
#include <FEXCore/fextl/set.h>
#include <FEXCore/fextl/string.h>
+1 -1
View File
@@ -9,7 +9,6 @@ $end_info$
*/
#include <cstdint>
#include "FEXCore/Utils/DeferredSignalMutex.h"
#include "Interface/Context/Context.h"
#include "Interface/Core/LookupCache.h"
#include "Interface/Core/CPUID.h"
@@ -45,6 +44,7 @@ $end_info$
#include <FEXCore/Utils/Event.h>
#include <FEXCore/Utils/File.h>
#include <FEXCore/Utils/LogManager.h>
#include "FEXCore/Utils/SignalScopeGuards.h"
#include <FEXCore/Utils/Threads.h>
#include <FEXCore/Utils/Profiler.h>
#include <FEXCore/fextl/fmt.h>
@@ -5,8 +5,8 @@
#include <FEXCore/Utils/Allocator.h>
#include <FEXCore/Utils/LogManager.h>
#include <FEXCore/Utils/MathUtils.h>
#include <FEXCore/Utils/SignalScopeGuards.h>
#include <FEXCore/fextl/sstream.h>
#include <FEXCore/Utils/DeferredSignalMutex.h>
#include <FEXHeaderUtils/Syscalls.h>
#include <FEXHeaderUtils/TypeDefines.h>
#include <FEXCore/fextl/memory.h>
@@ -111,6 +111,7 @@ namespace FEXCore {
};
#endif
// Helper class to manage deferred signal refcounting within a block scope
class DeferredSignalRefCountGuard final {
public:
explicit DeferredSignalRefCountGuard(FEXCore::Core::InternalThreadState *Thread) : Thread(Thread) {
@@ -148,7 +149,7 @@ namespace FEXCore {
};
#ifndef _WIN32
// TODO: Duplicated, unify with ScopedSignalMask
// Helper class to mask POSIX signals within a block scope
class ScopedSignalMasker final {
public:
explicit ScopedSignalMasker(uint64_t Mask) : OriginalMask(0) {
@@ -173,6 +174,33 @@ namespace FEXCore {
};
#endif
/**
* @brief Produces a wrapper object around a scoped lock of the given mutex
* while ensuring POSIX signals are masked while the mutex is locked
*
* Use this to prevent reentrancy issues of C++ mutexes with certain signal handlers.
* Common examples of such issues are:
* - C++ mutexes not unlocking due to a signal handler calling longjmp from within a scope owning the mutex
* - The signal handler itself using a mutex that would be re-locked if the handler gets invoked
* again before unlocking
*
* Ownership of the returned object may be moved, but it is NOT SAFE to move across threads.
*/
template<template<typename> class LockType = std::unique_lock, typename MutexType>
[[nodiscard]] static auto MaskSignalsAndLockMutex(MutexType& mutex, uint64_t Mask = ~0ULL) {
#ifndef _WIN32
// Signals are masked first, and then the lock is acquired
struct {
ScopedSignalMasker mask;
LockType<MutexType> lock;
} scope_guard { ScopedSignalMasker { Mask }, LockType<MutexType> { mutex } };
return scope_guard;
#else
// TODO: Doesn't block signals which may or may not cause issues.
return LockType<MutexType> { mutex };
#endif
}
/**
* @brief Produces a wrapper object around a scoped lock of the given mutex
* while bumping the Thread's deferred signal refcount while the mutex is
@@ -1,69 +0,0 @@
// SPDX-License-Identifier: MIT
#pragma once
#include <atomic>
#include <cstdint>
#include <mutex>
#include <optional>
#ifndef _WIN32
#include <signal.h>
#include <sys/syscall.h>
#endif
#include <unistd.h>
namespace FHU {
#ifndef _WIN32
/**
* Masks POSIX signals for the scope the object is active in
*/
class ScopedSignalMasker final {
public:
explicit ScopedSignalMasker(uint64_t Mask) : OriginalMask(0) {
// Mask all signals, storing the original incoming mask
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &Mask, &*OriginalMask, sizeof(*OriginalMask));
}
// Move-only type
ScopedSignalMasker(const ScopedSignalMasker&) = delete;
ScopedSignalMasker& operator=(ScopedSignalMasker&) = delete;
ScopedSignalMasker(ScopedSignalMasker&& rhs) : OriginalMask(rhs.OriginalMask) {
rhs.OriginalMask.reset();
}
~ScopedSignalMasker() {
if (OriginalMask) {
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &OriginalMask, nullptr, sizeof(*OriginalMask));
}
}
private:
std::optional<uint64_t> OriginalMask{};
};
#endif
/**
* @brief Produces a wrapper object around a scoped lock of the given mutex
* while ensuring POSIX signals are masked while the mutex is locked
*
* Use this to prevent reentrancy issues of C++ mutexes with certain signal handlers.
* Common examples of such issues are:
* - C++ mutexes not unlocking due to a signal handler calling longjmp from within a scope owning the mutex
* - The signal handler itself using a mutex that would be re-locked if the handler gets invoked
* again before unlocking
*
* Ownership of the returned object may be moved, but it is NOT SAFE to move across threads.
*/
template<template<typename> class LockType = std::unique_lock, typename MutexType>
[[nodiscard]] static auto MaskSignalsAndLockMutex(MutexType& mutex, uint64_t Mask = ~0ULL) {
#ifndef _WIN32
// Signals are masked first, and then the lock is acquired
struct {
ScopedSignalMasker mask;
LockType<MutexType> lock;
} scope_guard { ScopedSignalMasker { Mask }, LockType<MutexType> { mutex } };
return scope_guard;
#else
// TODO: Doesn't block signals which may or may not cause issues.
return LockType<MutexType> { mutex };
#endif
}
}
@@ -16,7 +16,7 @@ $end_info$
#include <FEXCore/HLE/SourcecodeResolver.h>
#include <FEXCore/IR/IR.h>
#include <FEXCore/Utils/CompilerDefs.h>
#include <FEXCore/Utils/DeferredSignalMutex.h>
#include <FEXCore/Utils/SignalScopeGuards.h>
#include <FEXCore/fextl/fmt.h>
#include <FEXCore/fextl/map.h>
#include <FEXCore/fextl/memory.h>
@@ -16,11 +16,10 @@ $end_info$
#include "LinuxSyscalls/Syscalls.h"
#include <FEXHeaderUtils/TypeDefines.h>
#include <FEXHeaderUtils/ScopedSignalMask.h>
#include <FEXCore/Debug/InternalThreadState.h>
#include <FEXCore/Utils/LogManager.h>
#include <FEXCore/Utils/MathUtils.h>
#include <FEXCore/Utils/DeferredSignalMutex.h>
#include <FEXCore/Utils/SignalScopeGuards.h>
namespace FEX::HLE {
@@ -55,7 +54,7 @@ bool SyscallHandler::HandleSegfault(FEXCore::Core::InternalThreadState *Thread,
{
// Can't use the deferred signal lock in the SIGSEGV handler.
auto lk = FHU::MaskSignalsAndLockMutex<std::shared_lock>(_SyscallHandler->VMATracking.Mutex);
auto lk = FEXCore::MaskSignalsAndLockMutex<std::shared_lock>(_SyscallHandler->VMATracking.Mutex);
auto VMATracking = &_SyscallHandler->VMATracking;