Fix for crash when exiting whilst NewGRF scan still in progress
See: https://github.com/OpenTTD/OpenTTD/issues/8760
This commit is contained in:
@@ -344,6 +344,7 @@ static std::vector<GRFMD5SumState> _grf_md5_pending;
|
|||||||
static std::condition_variable _grf_md5_full_cv;
|
static std::condition_variable _grf_md5_full_cv;
|
||||||
static std::condition_variable _grf_md5_empty_cv;
|
static std::condition_variable _grf_md5_empty_cv;
|
||||||
static std::condition_variable _grf_md5_done_cv;
|
static std::condition_variable _grf_md5_done_cv;
|
||||||
|
static std::atomic<bool> _abort_grf_scan;
|
||||||
static const uint GRF_MD5_PENDING_MAX = 8;
|
static const uint GRF_MD5_PENDING_MAX = 8;
|
||||||
|
|
||||||
static void CalcGRFMD5SumFromState(const GRFMD5SumState &state)
|
static void CalcGRFMD5SumFromState(const GRFMD5SumState &state)
|
||||||
@@ -373,7 +374,7 @@ void CalcGRFMD5Thread()
|
|||||||
_grf_md5_pending.pop_back();
|
_grf_md5_pending.pop_back();
|
||||||
lk.unlock();
|
lk.unlock();
|
||||||
if (full) _grf_md5_full_cv.notify_one();
|
if (full) _grf_md5_full_cv.notify_one();
|
||||||
CalcGRFMD5SumFromState(state);
|
if (!_abort_grf_scan.load(std::memory_order_relaxed)) CalcGRFMD5SumFromState(state);
|
||||||
lk.lock();
|
lk.lock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -728,6 +729,8 @@ public:
|
|||||||
|
|
||||||
bool GRFFileScanner::AddFile(const std::string &filename, size_t basepath_length, const std::string &tar_filename)
|
bool GRFFileScanner::AddFile(const std::string &filename, size_t basepath_length, const std::string &tar_filename)
|
||||||
{
|
{
|
||||||
|
if (_abort_grf_scan.load(std::memory_order_relaxed)) return false;
|
||||||
|
|
||||||
GRFConfig *c = new GRFConfig(filename.c_str() + basepath_length);
|
GRFConfig *c = new GRFConfig(filename.c_str() + basepath_length);
|
||||||
|
|
||||||
bool added = FillGRFDetails(c, false);
|
bool added = FillGRFDetails(c, false);
|
||||||
@@ -846,6 +849,11 @@ void ScanNewGRFFiles(NewGRFScanCallback *callback)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AbortScanNewGRFFiles()
|
||||||
|
{
|
||||||
|
_abort_grf_scan.store(true, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a NewGRF in the scanned list.
|
* Find a NewGRF in the scanned list.
|
||||||
* @param grfid GRFID to look for,
|
* @param grfid GRFID to look for,
|
||||||
|
@@ -222,6 +222,7 @@ struct NewGRFScanCallback {
|
|||||||
size_t GRFGetSizeOfDataSection(FILE *f);
|
size_t GRFGetSizeOfDataSection(FILE *f);
|
||||||
|
|
||||||
void ScanNewGRFFiles(NewGRFScanCallback *callback);
|
void ScanNewGRFFiles(NewGRFScanCallback *callback);
|
||||||
|
void AbortScanNewGRFFiles();
|
||||||
const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum = nullptr, uint32 desired_version = 0);
|
const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum = nullptr, uint32 desired_version = 0);
|
||||||
GRFConfig *GetGRFConfig(uint32 grfid, uint32 mask = 0xFFFFFFFF);
|
GRFConfig *GetGRFConfig(uint32 grfid, uint32 mask = 0xFFFFFFFF);
|
||||||
GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only);
|
GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only);
|
||||||
|
@@ -1006,8 +1006,10 @@ int openttd_main(int argc, char *argv[])
|
|||||||
|
|
||||||
CrashLog::MainThreadExitCheckPendingCrashlog();
|
CrashLog::MainThreadExitCheckPendingCrashlog();
|
||||||
|
|
||||||
|
AbortScanNewGRFFiles();
|
||||||
WaitTillSaved();
|
WaitTillSaved();
|
||||||
WaitTillGeneratedWorld(); // Make sure any generate world threads have been joined.
|
WaitTillGeneratedWorld(); // Make sure any generate world threads have been joined.
|
||||||
|
WaitUntilModalProgressCompleted();
|
||||||
|
|
||||||
/* only save config if we have to */
|
/* only save config if we have to */
|
||||||
if (_save_config) {
|
if (_save_config) {
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
|
#include "video/video_driver.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -64,3 +65,22 @@ void SleepWhileModalProgress(int milliseconds)
|
|||||||
std::unique_lock<std::mutex> lk(_modal_progress_cv_mutex);
|
std::unique_lock<std::mutex> lk(_modal_progress_cv_mutex);
|
||||||
_modal_progress_cv.wait_for(lk, std::chrono::milliseconds(milliseconds), []{ return !_in_modal_progress; });
|
_modal_progress_cv.wait_for(lk, std::chrono::milliseconds(milliseconds), []{ return !_in_modal_progress; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WaitUntilModalProgressCompleted()
|
||||||
|
{
|
||||||
|
if (HasModalProgress()) {
|
||||||
|
_modal_progress_paint_mutex.unlock();
|
||||||
|
_modal_progress_work_mutex.unlock();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(_modal_progress_cv_mutex);
|
||||||
|
_modal_progress_cv.wait(lk, []{ return !_in_modal_progress; });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modal progress thread may need blitter access while we are waiting for it. */
|
||||||
|
VideoDriver::GetInstance()->ReleaseBlitterLock();
|
||||||
|
_modal_progress_paint_mutex.lock();
|
||||||
|
VideoDriver::GetInstance()->AcquireBlitterLock();
|
||||||
|
_modal_progress_work_mutex.lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -40,6 +40,7 @@ static inline bool UseThreadedModelProgress()
|
|||||||
bool IsFirstModalProgressLoop();
|
bool IsFirstModalProgressLoop();
|
||||||
void SetModalProgress(bool state);
|
void SetModalProgress(bool state);
|
||||||
void SleepWhileModalProgress(int milliseconds);
|
void SleepWhileModalProgress(int milliseconds);
|
||||||
|
void WaitUntilModalProgressCompleted();
|
||||||
|
|
||||||
extern std::mutex _modal_progress_work_mutex;
|
extern std::mutex _modal_progress_work_mutex;
|
||||||
extern std::mutex _modal_progress_paint_mutex;
|
extern std::mutex _modal_progress_paint_mutex;
|
||||||
|
Reference in New Issue
Block a user