diff options
author | Patric Stout <truebrain@openttd.org> | 2021-06-17 20:10:40 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-17 20:10:40 +0200 |
commit | b45c006ab9bdfb92fa6be66dcfa00099adbb85a8 (patch) | |
tree | 0c4641a44cd4447ed598bcef52a0fee8e7238625 | |
parent | c12a152ec972309a87ab1637091990520ce9c123 (diff) | |
download | openttd-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.
-rw-r--r-- | src/thread.h | 11 |
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 { |