Emulator Issues #12045
Dolphin crashes when stopping emulation during movie recording
Affects various games (but not all behave in the same way). Tested:
- GC IPL (NTSC 1.2): Hang or failed ImGui assertion
- Paper Mario TTYD (G8ME01, db9a997a617ee03bbc32336d6945ec02): Hang or failed ImGui assertion
- Kororinpa (RCPE18, 7697a6d5212b672845e6baa15d09fbc7): EXI_DeviceIPL error
- Pokémon Battle Revolution (RPBE01, ): EXI_DeviceIPL error
- Wii Sports (Rev 1, RSPE01, b6d6d751d4cad1880bee742594af6f76): Does not crash, but logs a warning
What's the problem? Describe what went wrong.
Dolphin crashes when stopping emulation during movie recording.
What steps will reproduce the problem?
- Start a title, and then start recording input (or, select "start recording input" while a game is selected).
- Click stop (or close the render window).
- Dolphin will prompt to save the movie file; either save it or cancel (if saved, the file appears to be correctly written)
- Dolphin will crash (for some titles).
Is the issue present in the latest development version? For future reference, please also write down the version number of the latest development version.
5.0-11824 and (dirty) 5.0-11836.
Is the issue present in the latest stable version?
No, not present in 5.0. Note that 5.0 does not appear to have any way to stop recording input other than stopping emulation.
If the issue isn't present in the latest stable version, which is the first broken version?
Not tested. Probably introduced whenever Qt got movie recording, but I don't think it's useful to bisect for that.
What are your PC specifications?
- CPU: AMD A6-340M APU with Radeon(tm) Graphics, 1500 Mhz, 4 Core(s), 4 Logical Processor(s)
- GPU: AMD Radeon HD 6520G
- OS: Windows 10 Pro (Insider preview) 10.0.19041.172
Is there anything else that can help developers narrow down the issue?
Failed assertion message from ImGui (appears to happen with GameCube titles):
Assertion failed! Program: C:\Users\Pokechu22\Downloads\Dolphin-x64\Dolphin.exe File: C:\buildbot\release-win-x64\build\Externals...\imgui.cpp Line: 3079 Expression: GImGui != 0 && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?" For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts (Press Retry to debug the application - JIT must be enabled)
On some Wii titles, a panic alert will occur for line 419 of EXI_DeviceIPL (
ASSERT(!Core::WantsDeterminism())). Dolphin also deadlocks with this message (after 5.0-11832, it no longer deadlocks, but clicking "yes" or "ignore" causes a crash).
Wii Sports does not crash, but there is a related-looking message:
17:44:599 Core\CoreTiming.cpp:266 E[PowerPC]: Someone scheduled an off-thread "IOSNotifyPowerButton" event while netplay or movie play/record was active. This is likely to cause a desync.
Looks like Wii Sports actually can have the same EXI_DeviceIPL issue, though it's less common (I had it happen while debugging after I resumed from a breakpoint).
The EXI_DeviceIPL case happens because
GetEmulatedTime checks if a movie is active or netplay is active and gives special results, and then asserts that there would be no determinism otherwise. However,
Movie::EndPlayInput immediately stops movie recording, but queues the call to
Core::UpdateWantDeterminism, so there is a period where neither a movie nor netplay are active but determinism is wanted. (This happens on Wii because it triggers a emulated shutdown, which doesn't immediately stop the system. The gamecube has no such shutdown system). Note that this queueing was added in this commit from PR #3794, which also fixes #8718, so it can't just be removed.
The imgui assertion comes from the video backend being shut down when the Video thread (or CPU-GPU thread) exits, which in turn calls
ImGui::DestoryContext(). (The renderers also call
g_renderer.reset() later.) However, before this,
MainWindow::OnStopRecording() is called, which calls
MainWindow::OnExportRecording(), which pauses and then resumes the core. However, this triggers an event which eventually makes it to
RenderWidget's listener for
EmulationStateChanged, which calls
RenderWidget::SetImGuiKeyMap. I'm not entirely sure of the thread parts of this, but it looks like a race condition exists where both the video backend shutdown and
SetImGuiKeyMap happen at the same time, leading to the
ImGui::GetIO call failing with ImGui uninitialized. (I've also sometimes had the
g_renderer->GetImGuiLock() call fail with
g_renderer being null, which further indicates a race condition.)
I'm not sure how to properly fix either of these, though.