IPC_HLE: Close file handles before savestating. Fixes DKCR crashing.

Donkey Kong Country Returns is writing new data to some files in /tmp
when loading each level. But the savestate code was opening the files
a second time and reading some old and stale data out.

As of #3798, dolphin now correctly restores that stale data to /tmp,
which broke DKCR (and probally countless other games).

This PR closes all file handles before saving and loading savestates,
which flushes the data out and pervents this issue. (old savestates
are corrupted and will still cause crashes if loaded)
This commit is contained in:
Scott Mansell 2016-05-29 14:56:49 +12:00
parent 6233620bde
commit f419faa408
4 changed files with 21 additions and 8 deletions

View File

@ -270,11 +270,11 @@ void DoState(PointerWrap &p)
p.Do(reply_queue);
p.Do(last_reply_time);
if (p.GetMode() == PointerWrap::MODE_READ)
// We need to make sure all file handles are closed so WII_IPC_Devices_fs::DoState can successfully save or re-create /tmp
for (auto& descriptor : g_FdMap)
{
// We need to make sure all file handles are closed so WII_IPC_Devices_fs::DoState can successfully re-create /tmp
for (u32 i = 0; i < IPC_MAX_FDS; i++)
g_FdMap[i].reset();
if (descriptor)
descriptor->PrepareForState(p.GetMode());
}
for (const auto& entry : g_DeviceMap)

View File

@ -109,6 +109,11 @@ public:
{
}
// Release any resources which might interfere with savestating.
virtual void PrepareForState(PointerWrap::Mode mode)
{
}
virtual void DoState(PointerWrap& p)
{
DoStateShared(p);

View File

@ -356,6 +356,14 @@ IPCCommandResult CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress)
return GetDefaultReply();
}
void CWII_IPC_HLE_Device_FileIO::PrepareForState(PointerWrap::Mode mode)
{
// Temporally close the file, to prevent any issues with the savestating of /tmp
// it can be opened again with another call to OpenFile()
m_file.reset();
}
void CWII_IPC_HLE_Device_FileIO::DoState(PointerWrap &p)
{
DoStateShared(p);
@ -365,8 +373,7 @@ void CWII_IPC_HLE_Device_FileIO::DoState(PointerWrap &p)
m_filepath = HLE_IPC_BuildFilename(m_Name);
if (p.GetMode() == PointerWrap::MODE_READ)
{
OpenFile();
}
// The file was closed during state (and might now be pointing at another file)
// Open it again
OpenFile();
}

View File

@ -26,6 +26,7 @@ public:
IPCCommandResult Read(u32 _CommandAddress) override;
IPCCommandResult Write(u32 _CommandAddress) override;
IPCCommandResult IOCtl(u32 _CommandAddress) override;
void PrepareForState(PointerWrap::Mode mode) override;
void DoState(PointerWrap &p) override;
void OpenFile();