summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Lutz <michi@icosahedron.de>2021-03-13 21:34:51 +0100
committerMichael Lutz <michi@icosahedron.de>2021-03-13 22:09:05 +0100
commit13011e00c6330e6d745f319766574d2cd78a1162 (patch)
treed6e7c2494036e39453705951785e2b85253ac741 /src
parent062eeb9810b1c222cb9b0cb331041c0934e49682 (diff)
downloadopenttd-13011e00c6330e6d745f319766574d2cd78a1162.tar.xz
Fix #8860: [Win32] Crashlog window wasn't reliably shown for crashes not on the main thread.
Diffstat (limited to 'src')
-rw-r--r--src/crashlog.h6
-rw-r--r--src/os/macosx/crashlog_osx.cpp4
-rw-r--r--src/os/unix/crashlog_unix.cpp4
-rw-r--r--src/os/windows/crashlog_win.cpp41
-rw-r--r--src/thread.h2
5 files changed, 40 insertions, 17 deletions
diff --git a/src/crashlog.h b/src/crashlog.h
index 7f1ff47ed..7d15c3512 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 a1470b6d6..7fcb672a8 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 ee3f5823f..fc3682d02 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 b0667ad8f..76a05eaa9 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,6 +605,19 @@ static void CDECL CustomAbort(int signal)
/* static */ void CrashLog::InitialiseCrashLog()
{
+ CrashLog::InitThread();
+
+ /* SIGABRT is not an unhandled exception, so we need to intercept it. */
+ signal(SIGABRT, CustomAbort);
+#if defined(_MSC_VER)
+ /* Don't show abort message as we will get the crashlog window anyway. */
+ _set_abort_behavior(0, _WRITE_ABORT_MSG);
+#endif
+ SetUnhandledExceptionFilter(ExceptionHandler);
+}
+
+/* static */ void CrashLog::InitThread()
+{
#if defined(_M_AMD64) || defined(_M_ARM64)
CONTEXT ctx;
RtlCaptureContext(&ctx);
@@ -613,28 +626,22 @@ static void CDECL CustomAbort(int signal)
* 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)
+# if defined(_M_ARM64)
_safe_esp = (void *)(ctx.Sp - 8);
-#else
+# else
_safe_esp = (void *)(ctx.Rsp - 8);
-#endif
+# endif
#else
-#if defined(_MSC_VER)
+ void *safe_esp;
+# if defined(_MSC_VER)
_asm {
- mov _safe_esp, esp
+ mov safe_esp, esp
}
-#else
- asm("movl %esp, __safe_esp");
-#endif
-#endif
-
- /* SIGABRT is not an unhandled exception, so we need to intercept it. */
- signal(SIGABRT, CustomAbort);
-#if defined(_MSC_VER)
- /* Don't show abort message as we will get the crashlog window anyway. */
- _set_abort_behavior(0, _WRITE_ABORT_MSG);
+# else
+ asm("movl %esp, _safe_esp");
+# endif
+ _safe_esp = safe_esp;
#endif
- SetUnhandledExceptionFilter(ExceptionHandler);
}
/* The crash log GUI */
diff --git a/src/thread.h b/src/thread.h
index f45694930..f2a47e7bf 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -11,6 +11,7 @@
#define THREAD_H
#include "debug.h"
+#include "crashlog.h"
#include <system_error>
#include <thread>
@@ -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...);