summaryrefslogtreecommitdiff
path: root/src/thread.h
diff options
context:
space:
mode:
authorPatric Stout <truebrain@openttd.org>2021-06-17 20:10:40 +0200
committerGitHub <noreply@github.com>2021-06-17 20:10:40 +0200
commitb45c006ab9bdfb92fa6be66dcfa00099adbb85a8 (patch)
tree0c4641a44cd4447ed598bcef52a0fee8e7238625 /src/thread.h
parentc12a152ec972309a87ab1637091990520ce9c123 (diff)
downloadopenttd-b45c006ab9bdfb92fa6be66dcfa00099adbb85a8.tar.xz
Fix: on startup, NewGRF scan could case race-condition (#9382)
Creating a thread was not thread-safe. The irony. The video-driver has a function GameLoopPause() which first checks if the thread is the game-thread or not. For this it needs access to this->game_thread. This variable is set in StartNewThread(). However, due to timing, it is well possible GameLoopPause() is called from the thread well before this->game_thread is assigned. And so we have a race-condition! Simply solve this by preventing a thread to start till we are done with our bookkeeping.
Diffstat (limited to 'src/thread.h')
-rw-r--r--src/thread.h11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/thread.h b/src/thread.h
index bcd469081..24f4f8e2a 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -14,6 +14,7 @@
#include "crashlog.h"
#include <system_error>
#include <thread>
+#include <mutex>
/**
* Sleep on the current thread for a defined time.
@@ -46,7 +47,17 @@ inline bool StartNewThread(std::thread *thr, const char *name, TFn&& _Fx, TArgs&
{
#ifndef NO_THREADS
try {
+ static std::mutex thread_startup_mutex;
+ std::lock_guard<std::mutex> lock(thread_startup_mutex);
+
std::thread t([] (const char *name, TFn&& F, TArgs&&... A) {
+ /* Delay starting the thread till the main thread is finished
+ * with the administration. This prevent race-conditions on
+ * startup. */
+ {
+ std::lock_guard<std::mutex> lock(thread_startup_mutex);
+ }
+
SetCurrentThreadName(name);
CrashLog::InitThread();
try {