mirror of https://github.com/OpenTTD/OpenTTD
Fix #8860: [Win32] Crashlog window wasn't reliably shown for crashes not on the main thread.
parent
062eeb9810
commit
13011e00c6
|
@ -114,6 +114,12 @@ public:
|
||||||
*/
|
*/
|
||||||
static void InitialiseCrashLog();
|
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 SetErrorMessage(const char *message);
|
||||||
static void AfterCrashLogCleanup();
|
static void AfterCrashLogCleanup();
|
||||||
};
|
};
|
||||||
|
|
|
@ -257,3 +257,7 @@ void CDECL HandleCrash(int signum)
|
||||||
signal(*i, HandleCrash);
|
signal(*i, HandleCrash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void CrashLog::InitThread()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -181,3 +181,7 @@ static void CDECL HandleCrash(int signum)
|
||||||
signal(*i, HandleCrash);
|
signal(*i, HandleCrash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void CrashLog::InitThread()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -537,7 +537,7 @@ static void ShowCrashlogWindow();
|
||||||
* Stack pointer for use when 'starting' the crash handler.
|
* Stack pointer for use when 'starting' the crash handler.
|
||||||
* Not static as gcc's inline assembly needs it that way.
|
* 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)
|
static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep)
|
||||||
{
|
{
|
||||||
|
@ -605,28 +605,7 @@ static void CDECL CustomAbort(int signal)
|
||||||
|
|
||||||
/* static */ void CrashLog::InitialiseCrashLog()
|
/* static */ void CrashLog::InitialiseCrashLog()
|
||||||
{
|
{
|
||||||
#if defined(_M_AMD64) || defined(_M_ARM64)
|
CrashLog::InitThread();
|
||||||
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
|
|
||||||
|
|
||||||
/* SIGABRT is not an unhandled exception, so we need to intercept it. */
|
/* SIGABRT is not an unhandled exception, so we need to intercept it. */
|
||||||
signal(SIGABRT, CustomAbort);
|
signal(SIGABRT, CustomAbort);
|
||||||
|
@ -637,6 +616,34 @@ static void CDECL CustomAbort(int signal)
|
||||||
SetUnhandledExceptionFilter(ExceptionHandler);
|
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 */
|
/* The crash log GUI */
|
||||||
|
|
||||||
static bool _expanded;
|
static bool _expanded;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define THREAD_H
|
#define THREAD_H
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "crashlog.h"
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ inline bool StartNewThread(std::thread *thr, const char *name, TFn&& _Fx, TArgs&
|
||||||
try {
|
try {
|
||||||
std::thread t([] (const char *name, TFn&& F, TArgs&&... A) {
|
std::thread t([] (const char *name, TFn&& F, TArgs&&... A) {
|
||||||
SetCurrentThreadName(name);
|
SetCurrentThreadName(name);
|
||||||
|
CrashLog::InitThread();
|
||||||
try {
|
try {
|
||||||
/* Call user function with the given arguments. */
|
/* Call user function with the given arguments. */
|
||||||
F(A...);
|
F(A...);
|
||||||
|
|
Loading…
Reference in New Issue