From 0550ca0854d18860f23de7772ba0887c771b8c40 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 17 Jun 2021 20:10:40 +0200 Subject: [PATCH] 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. (cherry picked from commit b45c006ab9bdfb92fa6be66dcfa00099adbb85a8) --- src/thread.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/thread.h b/src/thread.h index 66581b7573..55b13ee5d5 100644 --- a/src/thread.h +++ b/src/thread.h @@ -14,6 +14,7 @@ #include "crashlog.h" #include #include +#include #if defined(__MINGW32__) #include "3rdparty/mingw-std-threads/mingw.thread.h" #endif @@ -97,7 +98,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 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 lock(thread_startup_mutex); + } + SetCurrentThreadName(name); PerThreadSetup(); CrashLog::InitThread();