Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #10435 from AdmiralCurtiss/savestate-crash
Core/State: Add some multithreading protections.
  • Loading branch information
JMC47 committed Feb 11, 2022
2 parents 9d69ca8 + 7331169 commit 9214174
Showing 1 changed file with 18 additions and 15 deletions.
33 changes: 18 additions & 15 deletions Source/Core/Core/State.cpp
Expand Up @@ -64,12 +64,13 @@ static AfterLoadCallbackFunc s_on_after_load_callback;
// Temporary undo state buffer
static std::vector<u8> g_undo_load_buffer;
static std::vector<u8> g_current_buffer;
static bool s_load_or_save_in_progress;
static std::mutex s_load_or_save_in_progress_mutex;

static std::mutex g_cs_undo_load_buffer;
static std::mutex g_cs_current_buffer;
static Common::Event g_compressAndDumpStateSyncEvent;

static std::recursive_mutex g_save_thread_mutex;
static std::thread g_save_thread;

// Don't forget to increase this after doing changes on the savestate system
Expand Down Expand Up @@ -403,11 +404,10 @@ static void CompressAndDumpState(CompressAndDumpState_args save_args)

void SaveAs(const std::string& filename, bool wait)
{
if (s_load_or_save_in_progress)
std::unique_lock lk(s_load_or_save_in_progress_mutex, std::try_to_lock);
if (!lk)
return;

s_load_or_save_in_progress = true;

Core::RunOnCPUThread(
[&] {
// Measure the size of the buffer.
Expand Down Expand Up @@ -435,8 +435,12 @@ void SaveAs(const std::string& filename, bool wait)
save_args.filename = filename;
save_args.wait = wait;

Flush();
g_save_thread = std::thread(CompressAndDumpState, save_args);
{
std::lock_guard lk(g_save_thread_mutex);
Flush();
g_save_thread = std::thread(CompressAndDumpState, save_args);
}

g_compressAndDumpStateSyncEvent.Wait();
}
else
Expand All @@ -446,8 +450,6 @@ void SaveAs(const std::string& filename, bool wait)
}
},
true);

s_load_or_save_in_progress = false;
}

bool ReadHeader(const std::string& filename, StateHeader& header)
Expand Down Expand Up @@ -550,17 +552,18 @@ static void LoadFileStateData(const std::string& filename, std::vector<u8>& ret_

void LoadAs(const std::string& filename)
{
if (!Core::IsRunning() || s_load_or_save_in_progress)
{
if (!Core::IsRunning())
return;
}
else if (NetPlay::IsNetPlayRunning())

if (NetPlay::IsNetPlayRunning())
{
OSD::AddMessage("Loading savestates is disabled in Netplay to prevent desyncs");
return;
}

s_load_or_save_in_progress = true;
std::unique_lock lk(s_load_or_save_in_progress_mutex, std::try_to_lock);
if (!lk)
return;

Core::RunOnCPUThread(
[&] {
Expand Down Expand Up @@ -617,8 +620,6 @@ void LoadAs(const std::string& filename)
s_on_after_load_callback();
},
true);

s_load_or_save_in_progress = false;
}

void SetOnAfterLoadCallback(AfterLoadCallbackFunc callback)
Expand Down Expand Up @@ -699,6 +700,8 @@ void SaveFirstSaved()

void Flush()
{
std::lock_guard lk(g_save_thread_mutex);

// If already saving state, wait for it to finish
if (g_save_thread.joinable())
g_save_thread.join();
Expand Down

0 comments on commit 9214174

Please sign in to comment.