diff --git a/src/crashlog.h b/src/crashlog.h index 7f1ff47edd..7d15c3512f 100644 --- a/src/crashlog.h +++ b/src/crashlog.h @@ -114,6 +114,12 @@ public: */ static void InitialiseCrashLog(); + /** + * Prepare crash log handler for a newly started thread. + * @note must be implemented by all implementers of CrashLog. + */ + static void InitThread(); + static void SetErrorMessage(const char *message); static void AfterCrashLogCleanup(); }; diff --git a/src/os/macosx/crashlog_osx.cpp b/src/os/macosx/crashlog_osx.cpp index a1470b6d63..7fcb672a81 100644 --- a/src/os/macosx/crashlog_osx.cpp +++ b/src/os/macosx/crashlog_osx.cpp @@ -257,3 +257,7 @@ void CDECL HandleCrash(int signum) signal(*i, HandleCrash); } } + +/* static */ void CrashLog::InitThread() +{ +} diff --git a/src/os/unix/crashlog_unix.cpp b/src/os/unix/crashlog_unix.cpp index ee3f5823fd..fc3682d024 100644 --- a/src/os/unix/crashlog_unix.cpp +++ b/src/os/unix/crashlog_unix.cpp @@ -181,3 +181,7 @@ static void CDECL HandleCrash(int signum) signal(*i, HandleCrash); } } + +/* static */ void CrashLog::InitThread() +{ +} diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index b0667ad8f3..76a05eaa9e 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -537,7 +537,7 @@ static void ShowCrashlogWindow(); * Stack pointer for use when 'starting' the crash handler. * Not static as gcc's inline assembly needs it that way. */ -void *_safe_esp = nullptr; +thread_local void *_safe_esp = nullptr; static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) { @@ -605,28 +605,7 @@ static void CDECL CustomAbort(int signal) /* static */ void CrashLog::InitialiseCrashLog() { -#if defined(_M_AMD64) || defined(_M_ARM64) - CONTEXT ctx; - RtlCaptureContext(&ctx); - - /* The stack pointer for AMD64 must always be 16-byte aligned inside a - * function. As we are simulating a function call with the safe ESP value, - * we need to subtract 8 for the imaginary return address otherwise stack - * alignment would be wrong in the called function. */ -#if defined(_M_ARM64) - _safe_esp = (void *)(ctx.Sp - 8); -#else - _safe_esp = (void *)(ctx.Rsp - 8); -#endif -#else -#if defined(_MSC_VER) - _asm { - mov _safe_esp, esp - } -#else - asm("movl %esp, __safe_esp"); -#endif -#endif + CrashLog::InitThread(); /* SIGABRT is not an unhandled exception, so we need to intercept it. */ signal(SIGABRT, CustomAbort); @@ -637,6 +616,34 @@ static void CDECL CustomAbort(int signal) SetUnhandledExceptionFilter(ExceptionHandler); } +/* static */ void CrashLog::InitThread() +{ +#if defined(_M_AMD64) || defined(_M_ARM64) + CONTEXT ctx; + RtlCaptureContext(&ctx); + + /* The stack pointer for AMD64 must always be 16-byte aligned inside a + * function. As we are simulating a function call with the safe ESP value, + * we need to subtract 8 for the imaginary return address otherwise stack + * alignment would be wrong in the called function. */ +# if defined(_M_ARM64) + _safe_esp = (void *)(ctx.Sp - 8); +# else + _safe_esp = (void *)(ctx.Rsp - 8); +# endif +#else + void *safe_esp; +# if defined(_MSC_VER) + _asm { + mov safe_esp, esp + } +# else + asm("movl %esp, _safe_esp"); +# endif + _safe_esp = safe_esp; +#endif +} + /* The crash log GUI */ static bool _expanded; diff --git a/src/thread.h b/src/thread.h index f45694930b..f2a47e7bfe 100644 --- a/src/thread.h +++ b/src/thread.h @@ -11,6 +11,7 @@ #define THREAD_H #include "debug.h" +#include "crashlog.h" #include #include @@ -47,6 +48,7 @@ inline bool StartNewThread(std::thread *thr, const char *name, TFn&& _Fx, TArgs& try { std::thread t([] (const char *name, TFn&& F, TArgs&&... A) { SetCurrentThreadName(name); + CrashLog::InitThread(); try { /* Call user function with the given arguments. */ F(A...);