[+] Linux Exception Handlers and AuExit::ETriggerLevel::eSigQuitNow
[*] Linux stability fixes [+] AuProcAddresses.UNIX.[cpp/hpp]
This commit is contained in:
parent
8b29e73f96
commit
2371794d47
@ -14,12 +14,15 @@ namespace Aurora::Exit
|
||||
// Runtime deinitialize
|
||||
eSafeTermination,
|
||||
|
||||
// A fatal exception was caught by the watchdog. The process is on its way out
|
||||
// A fatal exception was caught by the watchdog. The process is on its way out and there's nothing you can do about it.
|
||||
eFatalException,
|
||||
|
||||
// Control+C was sent, termination must follow
|
||||
// Control+C was sent, termination should follow. Filter with CancelExit.
|
||||
eSigTerminate,
|
||||
|
||||
// Do not attempt to block this signal. Terminal UX or system power events are asserting it's time to go.
|
||||
eSigQuitNow,
|
||||
|
||||
// Something went wrong in the process. These could be frequent depending on the process
|
||||
eProblematicEvent
|
||||
));
|
||||
|
@ -246,8 +246,8 @@ namespace Aurora
|
||||
{
|
||||
bool bFIODisableBatching { false };
|
||||
bool bIOLinuxHasProcIpcPerms { false };
|
||||
AuUInt8 uSignalTerminate { 27 };
|
||||
AuUInt8 uSignalGAIOWorkerThreadDone { 28 };
|
||||
AuUInt8 uSignalTerminate { 64 - 3 };
|
||||
AuUInt8 uSignalGAIOWorkerThreadDone { 64 - 4 };
|
||||
};
|
||||
|
||||
struct ProcessConfig
|
||||
|
@ -118,3 +118,25 @@ ANNOYING_TAGONLY(void *operator new[], PROTOTYPE_LATTER(std::size_t s, std::alig
|
||||
#include <AuroraAlloc.cpp>
|
||||
#endif
|
||||
*/
|
||||
|
||||
#if defined(AURORA_PLATFORM_LINUX)
|
||||
namespace std
|
||||
{
|
||||
struct type_info;
|
||||
}
|
||||
|
||||
extern void AU_NORETURN __au_cxa_throw(void *pException, std::type_info*, void (*fDtor)(void *pThis));
|
||||
|
||||
extern "C" inline void AU_NORETURN __cxa_throw(void *pException, std::type_info *typeInfo, void (*fDtor)(void *pThis))
|
||||
{
|
||||
__au_cxa_throw(pException, typeInfo, fDtor);
|
||||
}
|
||||
|
||||
extern "C" AuUInt32 _au_Unwind_RaiseException(struct _Unwind_Exception *pUnwind);
|
||||
|
||||
extern "C" AuUInt32 _Unwind_RaiseException(struct _Unwind_Exception *pUnwind)
|
||||
{
|
||||
return _au_Unwind_RaiseException(pUnwind);
|
||||
}
|
||||
|
||||
#endif
|
@ -9,6 +9,7 @@
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
#include <Time/Time.hpp>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define AURORA_IS_GLIBC
|
||||
|
||||
@ -25,6 +26,23 @@ namespace Aurora
|
||||
void InitLinuxAddresses()
|
||||
{
|
||||
pgetsockname = getsockname;
|
||||
|
||||
#if defined(RTLD_NEXT)
|
||||
p__cxa_throw = (decltype(p__cxa_throw))dlsym(RTLD_NEXT, "__cxa_throw");
|
||||
p_Unwind_RaiseException = (decltype(p_Unwind_RaiseException))dlsym(RTLD_NEXT, "_Unwind_RaiseException");
|
||||
#endif
|
||||
|
||||
#if defined(RTLD_DEFAULT)
|
||||
if (!p_Unwind_RaiseException)
|
||||
{
|
||||
p_Unwind_RaiseException = (decltype(p_Unwind_RaiseException))dlsym(RTLD_DEFAULT, "_Unwind_RaiseException");
|
||||
}
|
||||
|
||||
if (!p__cxa_throw)
|
||||
{
|
||||
p__cxa_throw = (decltype(p__cxa_throw))dlsym(RTLD_DEFAULT, "__cxa_throw");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
|
@ -65,4 +65,7 @@ namespace Aurora
|
||||
inline int (*pgetsockname)(int sockfd, struct sockaddr *addr,
|
||||
socklen_t *addrlen);
|
||||
|
||||
inline void (AU_NORETURN *p__cxa_throw)(void *pException, std::type_info *typeInfo, void (*fDtor)(void *pThis));
|
||||
|
||||
inline AuUInt32 (*p_Unwind_RaiseException)(void *pException);
|
||||
}
|
29
Source/AuProcAddresses.UNIX.cpp
Executable file
29
Source/AuProcAddresses.UNIX.cpp
Executable file
@ -0,0 +1,29 @@
|
||||
/***
|
||||
Copyright (C) 2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuProcAddresses.UNIX.cpp
|
||||
Date: 2024-3-5
|
||||
Author: Reece
|
||||
***/
|
||||
#include "RuntimeInternal.hpp"
|
||||
#include "AuProcAddresses.UNIX.hpp"
|
||||
#include <Source/Debug/ExceptionWatcher.Unix.hpp>
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
void PosixForkResetLocks();
|
||||
}
|
||||
|
||||
namespace Aurora
|
||||
{
|
||||
void PosixDoForkHooks()
|
||||
{
|
||||
Process::PosixForkResetLocks();
|
||||
Debug::DeinitSignalHandlers();
|
||||
}
|
||||
|
||||
void PosixTerminate()
|
||||
{
|
||||
killpg(0, SIGKILL);
|
||||
}
|
||||
}
|
14
Source/AuProcAddresses.UNIX.hpp
Executable file
14
Source/AuProcAddresses.UNIX.hpp
Executable file
@ -0,0 +1,14 @@
|
||||
/***
|
||||
Copyright (C) 2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuProcAddresses.UNIX.hpp
|
||||
Date: 2024-3-5
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora
|
||||
{
|
||||
void PosixDoForkHooks();
|
||||
void PosixTerminate();
|
||||
}
|
@ -9,10 +9,16 @@
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#include "AuProcAddresses.NT.hpp"
|
||||
#elif defined(AURORA_IS_LINUX_DERIVED)
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
#include "AuProcAddresses.Linux.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||
#include "AuProcAddresses.UNIX.hpp"
|
||||
#endif
|
||||
|
||||
namespace Aurora
|
||||
{
|
||||
void InitProcAddresses();
|
||||
|
@ -19,6 +19,10 @@
|
||||
#include "Stack.Unix.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||
#include "ExceptionWatcher.Unix.hpp"
|
||||
#endif
|
||||
|
||||
#include "ErrorStack.hpp"
|
||||
|
||||
namespace Aurora::Debug
|
||||
@ -379,7 +383,7 @@ namespace Aurora::Debug
|
||||
|
||||
try
|
||||
{
|
||||
backTraceBuffer.reserve(512 - 32); // 512 seems like a nice length minus some overhead for a bucket allocator
|
||||
backTraceBuffer.reserve(512 - 32); // 512 seems like a nice length minus some overhead for an allocators header
|
||||
|
||||
backTraceBuffer += fmt::format("\tAddress: 0x{:x} (0x{:x})", frame.relAddress ? frame.relAddress : frame.address, frame.relAddress ? frame.address : frame.relAddress);
|
||||
|
||||
@ -401,10 +405,36 @@ namespace Aurora::Debug
|
||||
}
|
||||
|
||||
if (frame.label)
|
||||
{
|
||||
auto parts = AuSplitString(frame.label.value(), "+");
|
||||
if (auto resultName = DemangleName(parts[0]))
|
||||
{
|
||||
if (resultName.value() == parts[0])
|
||||
{
|
||||
backTraceBuffer += fmt::format(" ({}) \n", frame.label.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
backTraceBuffer += fmt::format(" ({} a/k/a {}) \n", resultName.value(), frame.label.value());
|
||||
}
|
||||
}
|
||||
else if (auto resultName = DemangleName(frame.label.value()))
|
||||
{
|
||||
if (resultName.value() == frame.label.value())
|
||||
{
|
||||
backTraceBuffer += fmt::format(" ({}) \n", frame.label.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
backTraceBuffer += fmt::format(" ({} a/k/a {}) \n", resultName.value(), frame.label.value());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
backTraceBuffer += fmt::format(" ({}) \n", frame.label.value());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
backTraceBuffer += ", unknown function\n";
|
||||
}
|
||||
@ -464,5 +494,9 @@ namespace Aurora::Debug
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
InitNT();
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||
InitUNIX();
|
||||
#endif
|
||||
}
|
||||
}
|
@ -50,6 +50,8 @@ namespace Aurora::Debug
|
||||
|
||||
AUKN_SYM const AuString &ThreadMessage::ToString()
|
||||
{
|
||||
static const AuString kUnknownError = "Unknown Error.";
|
||||
|
||||
if (this->pStringMessage)
|
||||
{
|
||||
return *this->pStringMessage;
|
||||
@ -83,7 +85,7 @@ namespace Aurora::Debug
|
||||
return tlsLastMessageError = fmt::format("OS = {}", (AuUInt)*optOsErrorCode);
|
||||
}
|
||||
|
||||
return "Unknown error.";
|
||||
return kUnknownError;
|
||||
}
|
||||
|
||||
static thread_local ErrorStack *tlsErrorStackBase;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
Copyright (C) 2021-2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ExceptionWatcher.Linux.cpp
|
||||
Date: 2021-6-12
|
||||
@ -8,15 +8,427 @@
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "ExceptionWatcher.Unix.hpp"
|
||||
|
||||
#include "Debug.hpp"
|
||||
#include <Source/Telemetry/Telemetry.hpp>
|
||||
#include <Source/Grug/AuGrug.hpp>
|
||||
#include <Source/Console/Console.hpp>
|
||||
#include <Source/Exit/AuExit.hpp>
|
||||
#include "ErrorStack.hpp"
|
||||
|
||||
#if defined(AURORA_PLATFORM_LINUX)
|
||||
#include "unwind.h"
|
||||
#endif
|
||||
|
||||
#include "Stack.Unix.hpp"
|
||||
|
||||
#include <cxxabi.h>
|
||||
|
||||
#if defined(AURORA_PLATFORM_LINUX) && defined(AURORA_ARCH_X64)
|
||||
#define DEBUG_ABI_ALPHA
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_PLATFORM_LINUX) && (defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
|
||||
#define DEBUG_ABI_IS_IT_AND_SYSV_LIKE
|
||||
#endif
|
||||
|
||||
namespace Aurora::Debug
|
||||
{
|
||||
void PlatformHandleFatal(bool fatal, bool bNoExit)
|
||||
static const AuUInt8 kCriticalAlwaysCoreDumpSignals[] {
|
||||
SIGABRT,
|
||||
SIGBUS,
|
||||
SIGILL,
|
||||
SIGIOT,
|
||||
SIGQUIT,
|
||||
SIGSEGV,
|
||||
SIGSYS,
|
||||
SIGTRAP,
|
||||
//SIGUNUSED,
|
||||
SIGFPE,
|
||||
SIGXFSZ
|
||||
};
|
||||
|
||||
static const AuUInt8 kTypeIgnoreNOP = 0;
|
||||
static const AuUInt8 kTypeIgnoreAndLog = 1;
|
||||
static const AuUInt8 kTypeCoreDump = 2;
|
||||
|
||||
static AuUInt8 gSignalHandlerMap[64] {};
|
||||
|
||||
static void SaveMinidump(void *optContext,
|
||||
void *pException,
|
||||
int iSignal,
|
||||
AuUInt32 uThread,
|
||||
AuString &pathOut)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void PlatformHandleFatalEx(bool fatal, bool bNoExit, void *context, AuUInt32 uThreadID)
|
||||
{
|
||||
AuString path;
|
||||
|
||||
SaveMinidump(context, nullptr, 0, uThreadID, path);
|
||||
|
||||
if (fatal)
|
||||
{
|
||||
if (path.size())
|
||||
{
|
||||
Telemetry::NewBlackBoxEntryMinidump report {};
|
||||
report.includesRx = false;
|
||||
report.resource.path = path;
|
||||
report.resource.type = Telemetry::ENewBlackBoxResourceType::eLocal;
|
||||
Telemetry::ReportDyingBreath(report);
|
||||
}
|
||||
|
||||
PosixTerminate();
|
||||
}
|
||||
}
|
||||
|
||||
struct SigArrow : Grug::Arrow
|
||||
{
|
||||
int signal {};
|
||||
void *context {};
|
||||
AuUInt32 uPosixThread {};
|
||||
AuUInt thread;
|
||||
};
|
||||
|
||||
static void SendLogMessage(Grug::Arrow *pArrow)
|
||||
{
|
||||
auto pArrowEx = AuStaticCast<SigArrow>(pArrow);
|
||||
AuLogDbg("Caught signal {} ({}) on {}/{}", strsignal(pArrowEx->signal), pArrowEx->signal, pArrowEx->thread, pArrowEx->uPosixThread);
|
||||
|
||||
Exit::PostLevel((AuThreads::IAuroraThread *)pArrowEx->thread, Exit::ETriggerLevel::eProblematicEvent);
|
||||
}
|
||||
|
||||
static void SendCoreDump(Grug::Arrow *pArrow)
|
||||
{
|
||||
auto pArrowEx = AuStaticCast<SigArrow>(pArrow);
|
||||
|
||||
{
|
||||
StackTrace trace;
|
||||
|
||||
if (pArrowEx->context)
|
||||
{
|
||||
trace = DumpContext(pArrowEx->context);
|
||||
}
|
||||
|
||||
if (gRuntimeConfig.debug.bPrintExceptionStackTracesOut)
|
||||
{
|
||||
AuLogWarn("Fatal Signal: 0x{:x}, {} ({})", pArrowEx->thread, strsignal(pArrowEx->signal), pArrowEx->signal);
|
||||
AuLogWarn("{}", StringifyStackTrace(trace));
|
||||
}
|
||||
|
||||
{
|
||||
Telemetry::NewBlockboxEntry entry;
|
||||
entry.type = Telemetry::ENewBlackBoxEntry::eStackWarning;
|
||||
entry.stack.fenceId = ReportStackTrace(trace, AuToString(pArrowEx->signal));
|
||||
entry.stack.backtrace = trace;
|
||||
Telemetry::Report(entry);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Exit::PostLevel((AuThreads::IAuroraThread *)pArrowEx->thread, Exit::ETriggerLevel::eFatalException);
|
||||
}
|
||||
|
||||
{
|
||||
AuString path;
|
||||
SaveMinidump(pArrowEx->context, nullptr, pArrowEx->signal, pArrowEx->uPosixThread, path);
|
||||
|
||||
if (path.size())
|
||||
{
|
||||
Telemetry::NewBlackBoxEntryMinidump report {};
|
||||
report.includesRx = false;
|
||||
report.resource.path = path;
|
||||
report.resource.type = Telemetry::ENewBlackBoxResourceType::eLocal;
|
||||
Telemetry::ReportDyingBreath(report);
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
Grug::GrugFlushWrites();
|
||||
Grug::GrugFlushFlushs();
|
||||
Console::Pump();
|
||||
}
|
||||
|
||||
PosixTerminate();
|
||||
}
|
||||
|
||||
static void PosixCrashTrap(int signal, siginfo_t *si, void *context)
|
||||
{
|
||||
void (*pSendExitSignal_f)(Grug::Arrow *);
|
||||
SigArrow arrow;
|
||||
|
||||
arrow.signal = signal;
|
||||
arrow.thread = AuThreads::GetThreadId();
|
||||
arrow.context = context;
|
||||
arrow.uPosixThread = getpid();
|
||||
|
||||
switch (gSignalHandlerMap[signal])
|
||||
{
|
||||
case kTypeIgnoreNOP:
|
||||
return;
|
||||
|
||||
case kTypeIgnoreAndLog:
|
||||
pSendExitSignal_f = SendLogMessage;
|
||||
break;
|
||||
|
||||
case kTypeCoreDump:
|
||||
pSendExitSignal_f = SendCoreDump;
|
||||
break;
|
||||
}
|
||||
|
||||
Grug::HurlArrow(&arrow, pSendExitSignal_f, {});
|
||||
Grug::ArrowWait(&arrow);
|
||||
|
||||
if (pSendExitSignal_f == SendCoreDump)
|
||||
{
|
||||
PosixTerminate();
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformHandleFatal(bool bFatal, bool bNoExit)
|
||||
{
|
||||
PlatformHandleFatalEx(bFatal, bNoExit, nullptr, getpid());
|
||||
}
|
||||
|
||||
static void InstallSignalHandlerOnSignal(AuUInt8 uSignal)
|
||||
{
|
||||
struct sigaction action =
|
||||
{
|
||||
.sa_handler = (void (*)(int))PosixCrashTrap,
|
||||
.sa_flags = SA_ONSTACK
|
||||
};
|
||||
sigemptyset(&action.sa_mask);
|
||||
sigaction(uSignal, &action, nullptr);
|
||||
}
|
||||
|
||||
static void RemoveSignalHandlerOnSignal(AuUInt8 uSignal)
|
||||
{
|
||||
struct sigaction action =
|
||||
{
|
||||
.sa_handler = SIG_DFL,
|
||||
.sa_flags = SA_ONSTACK
|
||||
};
|
||||
sigemptyset(&action.sa_mask);
|
||||
sigaction(uSignal, &action, nullptr);
|
||||
}
|
||||
|
||||
static void OverrideCriticalSignals()
|
||||
{
|
||||
for (AU_ITERATE_N(i, AuArraySize(kCriticalAlwaysCoreDumpSignals)))
|
||||
{
|
||||
auto uSignal = kCriticalAlwaysCoreDumpSignals[i];
|
||||
gSignalHandlerMap[uSignal] = kTypeCoreDump;
|
||||
InstallSignalHandlerOnSignal(uSignal);
|
||||
}
|
||||
}
|
||||
|
||||
void InitUNIX()
|
||||
{
|
||||
|
||||
OverrideCriticalSignals();
|
||||
}
|
||||
|
||||
void DeinitSignalHandlers()
|
||||
{
|
||||
for (AU_ITERATE_N(uSignal, AuArraySize(gSignalHandlerMap)))
|
||||
{
|
||||
if (gSignalHandlerMap[uSignal] == kTypeIgnoreNOP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RemoveSignalHandlerOnSignal(uSignal);
|
||||
}
|
||||
}
|
||||
|
||||
static void ReportException(void *pException,
|
||||
std::type_info *pInfo,
|
||||
const StackTrace &trace,
|
||||
AuConsumer<const AuString &> func = {})
|
||||
{
|
||||
AuString message { "EMPTY" };
|
||||
|
||||
if (pInfo)
|
||||
{
|
||||
//AuLogDbg("Base RTTI of the type info: {}", ((char ****)pInfo)[0][-1][1]);
|
||||
bool bIsStdExceptionDerived {};
|
||||
|
||||
#if defined(DEBUG_ABI_IS_IT_AND_SYSV_LIKE)
|
||||
if (strcmp(((char ****)pInfo)[0][-1][1], "N10__cxxabiv120__si_class_type_infoE") == 0)
|
||||
{
|
||||
char **pInfoCur = ((char ****)pException)[0][-1];
|
||||
while (pInfoCur)
|
||||
{
|
||||
if (strcmp(pInfoCur[1], "St9exception") == 0)
|
||||
{
|
||||
bIsStdExceptionDerived = true;
|
||||
break;
|
||||
}
|
||||
auto pOld = pInfoCur;
|
||||
pInfoCur = (char **)pInfoCur[2];
|
||||
if (pOld == pInfoCur)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*pInfo == typeid(const char*))
|
||||
{
|
||||
message = fmt::format("Exception Type: {}, Message: {}", pInfo->name(), pException ? *(const char**)pException : "<NULL>");
|
||||
}
|
||||
else if (*pInfo == typeid(char* const))
|
||||
{
|
||||
message = fmt::format("Exception Type: {}, Message: {}", pInfo->name(), pException ? *(const char**)pException : "<NULL>");
|
||||
}
|
||||
#define ADD_FMT_PRIM(type) \
|
||||
else if (*pInfo == typeid(type)) \
|
||||
{ \
|
||||
message = fmt::format("Exception Type: {}, Data: {}", pInfo->name(), pException ? *(type*)pException : type {}); \
|
||||
}
|
||||
|
||||
ADD_FMT_PRIM(std::string)
|
||||
ADD_FMT_PRIM(double)
|
||||
ADD_FMT_PRIM(float)
|
||||
ADD_FMT_PRIM(AuUInt8)
|
||||
ADD_FMT_PRIM(AuUInt16)
|
||||
ADD_FMT_PRIM(AuUInt32)
|
||||
ADD_FMT_PRIM(AuUInt64)
|
||||
ADD_FMT_PRIM(AuInt8)
|
||||
ADD_FMT_PRIM(AuInt16)
|
||||
ADD_FMT_PRIM(AuInt32)
|
||||
ADD_FMT_PRIM(AuInt64)
|
||||
|
||||
else if (bIsStdExceptionDerived)
|
||||
{
|
||||
message = fmt::format("Exception Type: {}, Message: {}", pInfo->name(), ((std::exception *)pException)->what());
|
||||
}
|
||||
else
|
||||
{
|
||||
message = fmt::format("Exception Type: {}", pInfo->name());
|
||||
}
|
||||
}
|
||||
|
||||
if (func)
|
||||
{
|
||||
func(message);
|
||||
}
|
||||
|
||||
{
|
||||
Telemetry::NewBlockboxEntry entry;
|
||||
entry.type = Telemetry::ENewBlackBoxEntry::eStackWarning;
|
||||
entry.stack.fenceId = ReportStackTrace(trace, message);
|
||||
entry.stack.backtrace = trace;
|
||||
Telemetry::Report(entry);
|
||||
|
||||
auto pStr = AuMakeSharedPanic<AuString>(message);
|
||||
// auto pTrace = AuMakeSharedThrow<StackTrace>(trace);
|
||||
|
||||
if (ShouldPushErrorStackInternal())
|
||||
{
|
||||
auto pMessage = AuMakeSharedThrow<ThreadMessage>();
|
||||
pMessage->optStackTrace = trace;
|
||||
pMessage->pStringMessage = pStr;
|
||||
PushErrorStackInternal(pMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AU_NORETURN void __au_cxa_throw(void *pException, std::type_info *pInfo, void (*fDtor)(void *pThis))
|
||||
{
|
||||
if (Grug::IsGrug())
|
||||
{
|
||||
SysAssert(p__cxa_throw, "NST");
|
||||
p__cxa_throw(pException, pInfo, fDtor);
|
||||
}
|
||||
|
||||
{
|
||||
AU_DEBUG_MEMCRUNCH;
|
||||
|
||||
auto trace = GetStackTrace();
|
||||
|
||||
if (gRuntimeConfig.debug.bPrintExceptionStackTracesOut)
|
||||
{
|
||||
ReportException(pException, pInfo, trace, [&](const AuString &str)
|
||||
{
|
||||
AuLogWarn("Local Clang Exception: 0x{:x}, {}", AuUInt(pException), str.c_str());
|
||||
AuLogWarn("{}", StringifyStackTrace(trace));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportException(pException, pInfo, trace);
|
||||
}
|
||||
|
||||
AuExit::PostLevel(AuThreads::GetThread(), Aurora::Exit::ETriggerLevel::eProblematicEvent);
|
||||
}
|
||||
|
||||
{
|
||||
SysAssert(p__cxa_throw, "NST");
|
||||
p__cxa_throw(pException, pInfo, fDtor);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(AURORA_PLATFORM_LINUX)
|
||||
static _Unwind_Reason_Code __au_Unwind_RaiseException(void *pException, std::type_info *pInfo, struct _Unwind_Exception *pUnwind)
|
||||
{
|
||||
if (Grug::IsGrug())
|
||||
{
|
||||
SysAssert(p_Unwind_RaiseException, "URE");
|
||||
return (_Unwind_Reason_Code)p_Unwind_RaiseException(pUnwind);
|
||||
}
|
||||
|
||||
{
|
||||
AU_DEBUG_MEMCRUNCH;
|
||||
|
||||
auto trace = GetStackTrace();
|
||||
|
||||
if (gRuntimeConfig.debug.bPrintExceptionStackTracesOut)
|
||||
{
|
||||
ReportException(pException, pInfo, trace, [&](const AuString &str)
|
||||
{
|
||||
AuLogWarn("Local Linux Exception: 0x{:x}, {}", AuUInt(pException), str.c_str());
|
||||
AuLogWarn("{}", StringifyStackTrace(trace));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportException(pException, pInfo, trace);
|
||||
}
|
||||
|
||||
AuExit::PostLevel(AuThreads::GetThread(), Aurora::Exit::ETriggerLevel::eProblematicEvent);
|
||||
}
|
||||
|
||||
{
|
||||
SysAssert(p_Unwind_RaiseException, "URE");
|
||||
return (_Unwind_Reason_Code)p_Unwind_RaiseException(pUnwind);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
AUKN_SYM void AU_NORETURN __au_cxa_throw(void *pException, std::type_info *pInfo, void (*fDtor)(void *pThis))
|
||||
{
|
||||
Aurora::Debug::__au_cxa_throw(pException, pInfo, fDtor);
|
||||
}
|
||||
|
||||
#if defined(AURORA_PLATFORM_LINUX)
|
||||
|
||||
AUKN_SYM extern "C" _Unwind_Reason_Code _au_Unwind_RaiseException(struct _Unwind_Exception *pUnwind)
|
||||
{
|
||||
_Unwind_Exception *exception_header = pUnwind;
|
||||
|
||||
auto pException = (void **)(&pUnwind[1]);
|
||||
|
||||
#if defined(DEBUG_ABI_ALPHA)
|
||||
auto pInfo = *(std::type_info **)((char *)pUnwind - 80);
|
||||
// TODO: Test for clangs termination handler to somewhat verify that we are parsing a known structure layout
|
||||
#else
|
||||
std::type_info *pInfo { nullptr };
|
||||
#endif
|
||||
|
||||
return Aurora::Debug::__au_Unwind_RaiseException(pException, pInfo, pUnwind);
|
||||
}
|
||||
|
||||
#endif
|
@ -7,4 +7,8 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace Aurora::Debug
|
||||
{
|
||||
void InitUNIX();
|
||||
void DeinitSignalHandlers();
|
||||
}
|
@ -88,8 +88,8 @@ namespace Aurora::Debug
|
||||
|
||||
try
|
||||
{
|
||||
Grug::GrugFlushFlushs();
|
||||
Grug::GrugFlushWrites();
|
||||
Grug::GrugFlushFlushs();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -126,6 +126,8 @@ namespace Aurora::Debug
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
Win32Terminate();
|
||||
#elif defined(AURORA_IS_POSIX_DERIVED)
|
||||
PosixTerminate();
|
||||
#else
|
||||
#if defined(AURORA_COMPILER_GCC) || defined(AURORA_COMPILER_CLANG)
|
||||
__builtin_trap();
|
||||
|
@ -86,6 +86,11 @@ namespace Aurora::Debug
|
||||
return DumpContext((unw_context_t *)&uc);
|
||||
}
|
||||
|
||||
StackTrace DumpContext(void *pContext)
|
||||
{
|
||||
return DumpContext((unw_context_t *)pContext);
|
||||
}
|
||||
|
||||
StackTrace PlatformWalkCallStack()
|
||||
{
|
||||
#if 0
|
||||
|
@ -13,5 +13,7 @@ namespace Aurora::Debug
|
||||
{
|
||||
StackTrace DumpContext(ucontext_t &uc);
|
||||
|
||||
StackTrace DumpContext(void *pContext);
|
||||
|
||||
StackTrace PlatformWalkCallStack();
|
||||
}
|
@ -16,6 +16,11 @@ namespace Aurora::Exit
|
||||
PostLevel(AuThreads::GetThread(), Exit::ETriggerLevel::eSigTerminate);
|
||||
}
|
||||
|
||||
static void SendExitNowSignal(Grug::Arrow *)
|
||||
{
|
||||
PostLevel(AuThreads::GetThread(), Exit::ETriggerLevel::eSigQuitNow);
|
||||
}
|
||||
|
||||
static void HandleSigTerminate(int sig)
|
||||
{
|
||||
static Grug::Arrow arrow;
|
||||
@ -26,7 +31,7 @@ namespace Aurora::Exit
|
||||
}
|
||||
else
|
||||
{
|
||||
Grug::HurlArrow(&arrow, SendExitSignal, {});
|
||||
Grug::HurlArrow(&arrow, SendExitNowSignal, {});
|
||||
Grug::ArrowWait(&arrow);
|
||||
}
|
||||
}
|
||||
@ -41,7 +46,8 @@ namespace Aurora::Exit
|
||||
sigemptyset(&action.sa_mask);
|
||||
|
||||
sigaction(SIGINT, &action, nullptr);
|
||||
//sigaction(SIGTERM, &action, nullptr);
|
||||
sigaction(SIGTERM, &action, nullptr);
|
||||
sigaction(SIGTSTP, &action, nullptr);
|
||||
}
|
||||
|
||||
void DeinitUnix()
|
||||
@ -54,6 +60,7 @@ namespace Aurora::Exit
|
||||
sigemptyset(&action.sa_mask);
|
||||
|
||||
sigaction(SIGINT, &action, nullptr);
|
||||
//sigaction(SIGTERM, &action, nullptr);
|
||||
sigaction(SIGTERM, &action, nullptr);
|
||||
sigaction(SIGTSTP, &action, nullptr);
|
||||
}
|
||||
}
|
@ -32,7 +32,8 @@ namespace Aurora::Exit
|
||||
{
|
||||
static AuMutex gMutex;
|
||||
static AuList<AuTuple<AuSPtr<IExitSubscriber>, ETriggerLevel>> gTriggerSubscribers;
|
||||
static bool gIsAppRunning {true};
|
||||
static bool gIsAppRunning { true };
|
||||
static bool gIsAppForceTerminating { false };
|
||||
|
||||
static void DispatchHandlersForThread(AuThreads::IAuroraThread *pThread, ETriggerLevel level)
|
||||
{
|
||||
@ -83,11 +84,16 @@ namespace Aurora::Exit
|
||||
|
||||
//
|
||||
bOldTerminatingValue = gIsAppRunning;
|
||||
if (isTerminate || level == ETriggerLevel::eSigTerminate)
|
||||
if (isTerminate || level == ETriggerLevel::eSigTerminate || level == ETriggerLevel::eSigQuitNow)
|
||||
{
|
||||
gIsAppRunning = false;
|
||||
}
|
||||
|
||||
if (level == ETriggerLevel::eSigQuitNow)
|
||||
{
|
||||
gIsAppForceTerminating = true;
|
||||
}
|
||||
|
||||
static AuUInt32 gProblemCounter = {};
|
||||
|
||||
// Mitigate reused stack, nested try/catch, spam
|
||||
@ -134,18 +140,25 @@ namespace Aurora::Exit
|
||||
gHasSentTerminate |= isTerminate;
|
||||
}
|
||||
|
||||
if (gIsAppForceTerminating)
|
||||
{
|
||||
gHasCanceled = false;
|
||||
}
|
||||
|
||||
if ((level == ETriggerLevel::eSigTerminate && !gHasCanceled) ||
|
||||
level == ETriggerLevel::eFatalException ||
|
||||
level == ETriggerLevel::eSafeTermination)
|
||||
level == ETriggerLevel::eSafeTermination||
|
||||
level == ETriggerLevel::eSigQuitNow)
|
||||
{
|
||||
UnsafeProcessShutdownHook();
|
||||
}
|
||||
|
||||
// Force exit after calling the subscribers, should the level be eSigTerminate
|
||||
if (level == ETriggerLevel::eSigTerminate)
|
||||
if (level == ETriggerLevel::eSigTerminate ||
|
||||
level == ETriggerLevel::eSigQuitNow)
|
||||
{
|
||||
// HACK:
|
||||
if (gHasCanceled)
|
||||
if (gHasCanceled && !gIsAppForceTerminating)
|
||||
{
|
||||
gIsAppRunning = bOldTerminatingValue;
|
||||
}
|
||||
@ -178,7 +191,7 @@ namespace Aurora::Exit
|
||||
|
||||
AUKN_SYM bool IsAppRunning()
|
||||
{
|
||||
return gIsAppRunning;
|
||||
return gIsAppRunning && !gIsAppForceTerminating;
|
||||
}
|
||||
|
||||
AUKN_SYM void CancelExit()
|
||||
@ -194,6 +207,11 @@ namespace Aurora::Exit
|
||||
PostLevel(AuThreads::GetThread(), Exit::ETriggerLevel::eSigTerminate);
|
||||
}
|
||||
|
||||
static void SendExitNowSignal(Grug::Arrow *)
|
||||
{
|
||||
PostLevel(AuThreads::GetThread(), Exit::ETriggerLevel::eSigQuitNow);
|
||||
}
|
||||
|
||||
static void SendTerminateSignalAndBlock()
|
||||
{
|
||||
static Grug::Arrow arrow;
|
||||
@ -209,7 +227,14 @@ namespace Aurora::Exit
|
||||
{
|
||||
Exit::gHasCanceled = false;
|
||||
//SendTerminateSignalAndBlock();// for some reason we aren't getting win32 console flushes **reliably** :(
|
||||
if (ctrlType == CTRL_C_EVENT)
|
||||
{
|
||||
SendExitSignal(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendExitNowSignal(nullptr);
|
||||
}
|
||||
return !AuExchange(Exit::gHasCanceled, false);
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ namespace Aurora::IO::Adapters
|
||||
this->SignalComplete();
|
||||
}
|
||||
|
||||
void OnFailure()
|
||||
void OnFailure() override
|
||||
{
|
||||
this->bInProgress = false;
|
||||
this->Reset();
|
||||
|
@ -38,7 +38,7 @@ namespace Aurora::IO::Net
|
||||
// TODO: we really need to make a general purpose AuAsync IO pool and generic resolver replacer/hooking interface for net services.
|
||||
static auto GetGAIAsyncIOSignal()
|
||||
{
|
||||
return SIGUSR1 + gRuntimeConfig.linuxConfig.uSignalGAIOWorkerThreadDone;
|
||||
return gRuntimeConfig.linuxConfig.uSignalGAIOWorkerThreadDone;
|
||||
}
|
||||
|
||||
ThreadLocalCaughtCompletion::ThreadLocalCaughtCompletion(NetResolver *pParent) :
|
||||
@ -100,7 +100,7 @@ namespace Aurora::IO::Net
|
||||
NetResolver::NetResolver(const AuSPtr<INetWorker> &pWorker) :
|
||||
pWorker_(pWorker)
|
||||
{
|
||||
this->pEvent = AuLoop::NewLSEvent(false, false);
|
||||
this->pEvent = AuLoop::NewLSEventSlow(false, false);
|
||||
}
|
||||
|
||||
NetResolver::NetResolver(const AuSPtr<INetWorker> &pWorker,
|
||||
@ -108,7 +108,7 @@ namespace Aurora::IO::Net
|
||||
pCompletion_(pCompletion),
|
||||
pWorker_(pWorker)
|
||||
{
|
||||
this->pEvent = AuLoop::NewLSEvent(false, false);
|
||||
this->pEvent = AuLoop::NewLSEventSlow(false, false);
|
||||
}
|
||||
|
||||
NetResolver::~NetResolver()
|
||||
|
@ -75,23 +75,7 @@ namespace Aurora::IO::Net
|
||||
|
||||
if (!this->bDatagramMode)
|
||||
{
|
||||
AuLoop::ILSEvent *optEvent {};
|
||||
|
||||
if (this->pCompletionGroup_)
|
||||
{
|
||||
if (auto pLoopSource = this->pCompletionGroup_->GetTriggerLoopSource())
|
||||
{
|
||||
optEvent = AuStaticCast<Loop::LSEvent>(pLoopSource).get();
|
||||
}
|
||||
}
|
||||
|
||||
if (!optEvent)
|
||||
{
|
||||
if (auto pWaitable = this->pWaitable)
|
||||
{
|
||||
optEvent = pWaitable.get();
|
||||
}
|
||||
}
|
||||
AuLoop::ILSEvent *optEvent { this->GetAlertable() };
|
||||
|
||||
if (!UNIX::LinuxOverlappedSubmitRead(this->GetSocket(), 0, this, optEvent, true))
|
||||
{
|
||||
@ -161,23 +145,7 @@ namespace Aurora::IO::Net
|
||||
|
||||
if (!this->bDatagramMode)
|
||||
{
|
||||
AuLoop::ILSEvent *optEvent {};
|
||||
|
||||
if (this->pCompletionGroup_)
|
||||
{
|
||||
if (auto pLoopSource = this->pCompletionGroup_->GetTriggerLoopSource())
|
||||
{
|
||||
optEvent = AuStaticCast<Loop::LSEvent>(pLoopSource).get();
|
||||
}
|
||||
}
|
||||
|
||||
if (!optEvent)
|
||||
{
|
||||
if (auto pWaitable = this->pWaitable)
|
||||
{
|
||||
optEvent = pWaitable.get();
|
||||
}
|
||||
}
|
||||
AuLoop::ILSEvent *optEvent { this->GetAlertable() };
|
||||
|
||||
if (!UNIX::LinuxOverlappedSubmitWrite(this->GetSocket(), 0, this, optEvent))
|
||||
{
|
||||
@ -345,7 +313,11 @@ namespace Aurora::IO::Net
|
||||
return pWaitable;
|
||||
}
|
||||
|
||||
return this->pWaitable = AuLoop::NewLSEventSlow(false, true);
|
||||
if (auto pSocket = this->pSocket)
|
||||
{
|
||||
return AuStaticCast<AuLoop::LSEvent>(pSocket->ToWorkerEx()->ToEvent());
|
||||
}
|
||||
//return this->pWaitable = AuLoop::NewLSEventSlow(false, true);
|
||||
}
|
||||
|
||||
return {};
|
||||
@ -417,28 +389,30 @@ namespace Aurora::IO::Net
|
||||
return this->pSocket->ToPlatformHandle();
|
||||
}
|
||||
|
||||
int LinuxAsyncNetworkTransaction::GetAlertable()
|
||||
AuLoop::ILSEvent *LinuxAsyncNetworkTransaction::GetAlertable()
|
||||
{
|
||||
if (this->pCompletionGroup_)
|
||||
{
|
||||
auto pLoopSource = this->pCompletionGroup_->GetTriggerLoopSource();
|
||||
if (!pLoopSource)
|
||||
if (pLoopSource)
|
||||
{
|
||||
return -1;
|
||||
return AuStaticCast<Loop::LSEvent>(pLoopSource).get();
|
||||
}
|
||||
|
||||
return (int)AuStaticCast<Loop::LSEvent>(pLoopSource)->GetHandle();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (auto pWaitable = this->pWaitable)
|
||||
{
|
||||
return AuStaticCast<AuLoop::LSEvent>(pWaitable).get();
|
||||
}
|
||||
|
||||
if (auto pSocket = this->pSocket)
|
||||
{
|
||||
return (int)AuStaticCast<AuLoop::LSEvent>(pSocket->ToWorkerEx()->ToEvent())->GetHandle();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
return AuStaticCast<AuLoop::LSEvent>(pSocket->ToWorkerEx()->ToEvent()).get();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
@ -62,7 +62,7 @@ namespace Aurora::IO::Net
|
||||
void DispatchCb(AuUInt32 len);
|
||||
|
||||
int GetSocket();
|
||||
int GetAlertable();
|
||||
AuLoop::ILSEvent *GetAlertable();
|
||||
|
||||
bool TranslateLastError(bool bReturnValue);
|
||||
|
||||
|
@ -12,11 +12,6 @@
|
||||
#include <unistd.h>
|
||||
#include <Source/IO/FS/FS.hpp>
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
void PosixForkResetLocks();
|
||||
}
|
||||
|
||||
namespace Aurora::Processes
|
||||
{
|
||||
static void UnixOpenAsyncThread(AuString uri, bool bType)
|
||||
@ -65,7 +60,8 @@ namespace Aurora::Processes
|
||||
{
|
||||
setsid();
|
||||
|
||||
AuProcess::PosixForkResetLocks();
|
||||
PosixDoForkHooks();
|
||||
|
||||
auto optStringA = AuProcess::EnvironmentGetOne("container");
|
||||
auto optStringB = AuProcess::EnvironmentGetOne("AURORA_RUNTIME_USE_GDBUS_BIN_TO_PORTAL");
|
||||
bool bIsFireJail = optStringA && optStringA.Value() == "firejail";
|
||||
|
@ -46,11 +46,6 @@
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
void PosixForkResetLocks();
|
||||
}
|
||||
|
||||
namespace Aurora::Processes
|
||||
{
|
||||
static AuRWLock gRWLock;
|
||||
@ -566,7 +561,7 @@ namespace Aurora::Processes
|
||||
|
||||
void ProcessImpl::ForkMain()
|
||||
{
|
||||
AuProcess::PosixForkResetLocks();
|
||||
PosixDoForkHooks();
|
||||
|
||||
{
|
||||
::dup2(this->pipeStdIn_[0], STDIN_FILENO);
|
||||
|
Loading…
Reference in New Issue
Block a user