mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 21:41:26 +12:00
Fixup Savestate Segfault
This commit is contained in:
parent
2e824827b7
commit
453a3c4852
6 changed files with 33 additions and 18 deletions
|
@ -43,6 +43,7 @@
|
||||||
#include "../Crypto/unself.h"
|
#include "../Crypto/unself.h"
|
||||||
#include "../Crypto/unzip.h"
|
#include "../Crypto/unzip.h"
|
||||||
#include "util/logs.hpp"
|
#include "util/logs.hpp"
|
||||||
|
#include "util/init_mutex.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -2970,10 +2971,12 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||||
|
|
||||||
*join_thread = make_ptr(new named_thread("Emulation Join Thread"sv, [join_thread, savestate, allow_autoexit, this]() mutable
|
*join_thread = make_ptr(new named_thread("Emulation Join Thread"sv, [join_thread, savestate, allow_autoexit, this]() mutable
|
||||||
{
|
{
|
||||||
|
fs::pending_file file;
|
||||||
|
std::shared_ptr<stx::init_mutex> init_mtx = std::make_shared<stx::init_mutex>();
|
||||||
std::shared_ptr<bool> join_ended = std::make_shared<bool>(false);
|
std::shared_ptr<bool> join_ended = std::make_shared<bool>(false);
|
||||||
atomic_ptr<utils::serial> to_ar;
|
atomic_ptr<utils::serial> to_ar;
|
||||||
|
|
||||||
named_thread stop_watchdog("Stop Watchdog"sv, [&to_ar, join_ended, this]()
|
named_thread stop_watchdog("Stop Watchdog"sv, [&to_ar, init_mtx, join_ended, this]()
|
||||||
{
|
{
|
||||||
const auto closed_sucessfully = std::make_shared<atomic_t<bool>>(false);
|
const auto closed_sucessfully = std::make_shared<atomic_t<bool>>(false);
|
||||||
|
|
||||||
|
@ -3008,7 +3011,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||||
if (auto ar_ptr = to_ar.load())
|
if (auto ar_ptr = to_ar.load())
|
||||||
{
|
{
|
||||||
// Total amount of waiting: about 10s
|
// Total amount of waiting: about 10s
|
||||||
GetCallbacks().on_save_state_progress(closed_sucessfully, ar_ptr);
|
GetCallbacks().on_save_state_progress(closed_sucessfully, ar_ptr, init_mtx);
|
||||||
|
|
||||||
while (thread_ctrl::state() != thread_state::aborting)
|
while (thread_ctrl::state() != thread_state::aborting)
|
||||||
{
|
{
|
||||||
|
@ -3040,9 +3043,10 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||||
|
|
||||||
sys_log.notice("All threads have been stopped.");
|
sys_log.notice("All threads have been stopped.");
|
||||||
|
|
||||||
fs::pending_file file;
|
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
||||||
|
static_cast<void>(init_mtx->init());
|
||||||
|
|
||||||
while (savestate)
|
while (savestate)
|
||||||
{
|
{
|
||||||
path = get_savestate_file(m_title_id, m_path, 0, 0);
|
path = get_savestate_file(m_title_id, m_path, 0, 0);
|
||||||
|
@ -3068,8 +3072,9 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
to_ar = stx::make_single<utils::serial>();
|
auto serial_ptr = stx::make_single<utils::serial>();
|
||||||
to_ar.load()->m_file_handler = make_compressed_serialization_file_handler(file.file);
|
serial_ptr->m_file_handler = make_compressed_serialization_file_handler(file.file);
|
||||||
|
to_ar = std::move(serial_ptr);
|
||||||
|
|
||||||
signal_system_cache_can_stay();
|
signal_system_cache_can_stay();
|
||||||
break;
|
break;
|
||||||
|
@ -3235,6 +3240,9 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop_watchdog = thread_state::finished;
|
||||||
|
static_cast<void>(init_mtx->reset());
|
||||||
|
|
||||||
if (savestate)
|
if (savestate)
|
||||||
{
|
{
|
||||||
auto& ar = *to_ar.load();
|
auto& ar = *to_ar.load();
|
||||||
|
@ -3273,12 +3281,8 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||||
m_path = path;
|
m_path = path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ar.set_reading_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_watchdog = thread_state::aborting;
|
|
||||||
|
|
||||||
// Log additional debug information - do not do it on the main thread due to the concern of halting UI events
|
// Log additional debug information - do not do it on the main thread due to the concern of halting UI events
|
||||||
|
|
||||||
if (g_tty && sys_log.notice)
|
if (g_tty && sys_log.notice)
|
||||||
|
|
|
@ -64,7 +64,7 @@ struct EmuCallbacks
|
||||||
std::function<void()> on_ready;
|
std::function<void()> on_ready;
|
||||||
std::function<bool()> on_missing_fw;
|
std::function<bool()> on_missing_fw;
|
||||||
std::function<void(std::shared_ptr<atomic_t<bool>>, int)> on_emulation_stop_no_response;
|
std::function<void(std::shared_ptr<atomic_t<bool>>, int)> on_emulation_stop_no_response;
|
||||||
std::function<void(std::shared_ptr<atomic_t<bool>>, stx::shared_ptr<utils::serial>)> on_save_state_progress;
|
std::function<void(std::shared_ptr<atomic_t<bool>>, stx::shared_ptr<utils::serial>, std::shared_ptr<void>)> on_save_state_progress;
|
||||||
std::function<void(bool enabled)> enable_disc_eject;
|
std::function<void(bool enabled)> enable_disc_eject;
|
||||||
std::function<void(bool enabled)> enable_disc_insert;
|
std::function<void(bool enabled)> enable_disc_insert;
|
||||||
std::function<bool(bool, std::function<void()>)> try_to_quit; // (force_quit, on_exit) Try to close RPCS3
|
std::function<bool(bool, std::function<void()>)> try_to_quit; // (force_quit, on_exit) Try to close RPCS3
|
||||||
|
|
|
@ -148,7 +148,7 @@ void headless_application::InitializeCallbacks()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
callbacks.on_save_state_progress = [](std::shared_ptr<atomic_t<bool>>, stx::shared_ptr<utils::serial>)
|
callbacks.on_save_state_progress = [](std::shared_ptr<atomic_t<bool>>, stx::shared_ptr<utils::serial>, std::shared_ptr<void>)
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "Emu/Io/Null/null_camera_handler.h"
|
#include "Emu/Io/Null/null_camera_handler.h"
|
||||||
#include "Emu/Io/Null/null_music_handler.h"
|
#include "Emu/Io/Null/null_music_handler.h"
|
||||||
#include "Emu/vfs_config.h"
|
#include "Emu/vfs_config.h"
|
||||||
|
#include "util/init_mutex.hpp"
|
||||||
#include "Input/raw_mouse_handler.h"
|
#include "Input/raw_mouse_handler.h"
|
||||||
#include "trophy_notification_helper.h"
|
#include "trophy_notification_helper.h"
|
||||||
#include "save_data_dialog.h"
|
#include "save_data_dialog.h"
|
||||||
|
@ -666,9 +667,9 @@ void gui_application::InitializeCallbacks()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
callbacks.on_save_state_progress = [this](std::shared_ptr<atomic_t<bool>> closed_successfully, stx::shared_ptr<utils::serial> ar_ptr)
|
callbacks.on_save_state_progress = [this](std::shared_ptr<atomic_t<bool>> closed_successfully, stx::shared_ptr<utils::serial> ar_ptr, std::shared_ptr<void> init_mtx)
|
||||||
{
|
{
|
||||||
Emu.CallFromMainThread([this, closed_successfully, ar_ptr]
|
Emu.CallFromMainThread([this, closed_successfully, ar_ptr, init_mtx]
|
||||||
{
|
{
|
||||||
const auto half_seconds = std::make_shared<int>(1);
|
const auto half_seconds = std::make_shared<int>(1);
|
||||||
|
|
||||||
|
@ -684,8 +685,16 @@ void gui_application::InitializeCallbacks()
|
||||||
|
|
||||||
QTimer* update_timer = new QTimer(pdlg);
|
QTimer* update_timer = new QTimer(pdlg);
|
||||||
|
|
||||||
connect(update_timer, &QTimer::timeout, [pdlg, ar_ptr, half_seconds, text_base, closed_successfully]()
|
connect(update_timer, &QTimer::timeout, [pdlg, ar_ptr, half_seconds, text_base, closed_successfully, init_mtx]()
|
||||||
{
|
{
|
||||||
|
auto init = static_cast<stx::init_mutex*>(init_mtx.get())->access();
|
||||||
|
|
||||||
|
if (!init)
|
||||||
|
{
|
||||||
|
pdlg->reject();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
*half_seconds += 1;
|
*half_seconds += 1;
|
||||||
|
|
||||||
const usz bytes_written = ar_ptr->get_size();
|
const usz bytes_written = ar_ptr->get_size();
|
||||||
|
|
|
@ -150,12 +150,12 @@ usz uncompressed_serialization_file_handler::get_size(const utils::serial& ar, u
|
||||||
{
|
{
|
||||||
if (ar.is_writing())
|
if (ar.is_writing())
|
||||||
{
|
{
|
||||||
return m_file->size();
|
return *m_file ? m_file->size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const usz memory_available = ar.data_offset + ar.data.size();
|
const usz memory_available = ar.data_offset + ar.data.size();
|
||||||
|
|
||||||
if (memory_available >= recommended)
|
if (memory_available >= recommended || !*m_file)
|
||||||
{
|
{
|
||||||
// Avoid calling size() if possible
|
// Avoid calling size() if possible
|
||||||
return memory_available;
|
return memory_available;
|
||||||
|
@ -756,12 +756,12 @@ usz compressed_serialization_file_handler::get_size(const utils::serial& ar, usz
|
||||||
{
|
{
|
||||||
if (ar.is_writing())
|
if (ar.is_writing())
|
||||||
{
|
{
|
||||||
return m_file->size();
|
return *m_file ? m_file->size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const usz memory_available = ar.data_offset + ar.data.size();
|
const usz memory_available = ar.data_offset + ar.data.size();
|
||||||
|
|
||||||
if (memory_available >= recommended)
|
if (memory_available >= recommended || !*m_file)
|
||||||
{
|
{
|
||||||
// Avoid calling size() if possible
|
// Avoid calling size() if possible
|
||||||
return memory_available;
|
return memory_available;
|
||||||
|
|
|
@ -30,6 +30,7 @@ struct uncompressed_serialization_file_handler : utils::serialization_file_handl
|
||||||
}
|
}
|
||||||
|
|
||||||
uncompressed_serialization_file_handler(const uncompressed_serialization_file_handler&) = delete;
|
uncompressed_serialization_file_handler(const uncompressed_serialization_file_handler&) = delete;
|
||||||
|
uncompressed_serialization_file_handler& operator=(const uncompressed_serialization_file_handler&) = delete;
|
||||||
|
|
||||||
// Handle file read and write requests
|
// Handle file read and write requests
|
||||||
bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override;
|
bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override;
|
||||||
|
@ -68,6 +69,7 @@ struct compressed_serialization_file_handler : utils::serialization_file_handler
|
||||||
}
|
}
|
||||||
|
|
||||||
compressed_serialization_file_handler(const compressed_serialization_file_handler&) = delete;
|
compressed_serialization_file_handler(const compressed_serialization_file_handler&) = delete;
|
||||||
|
compressed_serialization_file_handler& operator=(const compressed_serialization_file_handler&) = delete;
|
||||||
|
|
||||||
// Handle file read and write requests
|
// Handle file read and write requests
|
||||||
bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override;
|
bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue