From f419faa4085a909a36622891037c16a2be0d9da7 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sun, 29 May 2016 14:56:49 +1200 Subject: [PATCH 1/2] 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) --- Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp | 8 ++++---- Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device.h | 5 +++++ .../Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp | 15 +++++++++++---- .../Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.h | 1 + 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp index 63c3d1720e..e67229e2ed 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp @@ -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) diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device.h index 0702b502be..a5100a4953 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device.h @@ -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); diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp index d92950b7f7..136533d03e 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp @@ -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(); } diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.h index c8715a4a86..880887a637 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.h @@ -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(); From 7d80aaedc7bbeae0fbad8e45a45747c60611b7d2 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sun, 29 May 2016 15:22:43 +1200 Subject: [PATCH 2/2] Cleanup: fix an incorrect variable name. For consistancy. --- Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp index e67229e2ed..529ab1b057 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp @@ -320,22 +320,22 @@ void DoState(PointerWrap &p) } else { - for (auto& dev : g_FdMap) + for (auto& descriptor : g_FdMap) { - u32 exists = dev ? 1 : 0; + u32 exists = descriptor ? 1 : 0; p.Do(exists); if (exists) { - u32 isHw = dev->IsHardware() ? 1 : 0; + u32 isHw = descriptor->IsHardware() ? 1 : 0; p.Do(isHw); if (isHw) { - u32 hwId = dev->GetDeviceID(); + u32 hwId = descriptor->GetDeviceID(); p.Do(hwId); } else { - dev->DoState(p); + descriptor->DoState(p); } } }