Audio: fix five hook/unhook concurrency + over-write bugs
Found by the mock-game capture/audio/hook stress test (toggling the audio subsystem while a game renders): 1. Guessed-stream silence over-WRITE: hk_ReleaseBuffer zeroed num_frames * guessed_block bytes, but a guess can be larger than the real per-frame size (e.g. an 8ch device guess for a 2ch game), so the memset wrote past the real buffer into adjacent audio memory -> intermittent access violation in the game. Fix: capture but do NOT silence a guessed stream (it stays audible -- echo); only an exact/override format, whose frame size is known, gets the no-echo silence. 2. VtableHook::remove nulled m_original, racing an in-flight detour into a null call -> keep it valid (the original function stays mapped). 3. g_ipc was a non-atomic pointer read on the hot path while unhook nulled it (TOCTOU) -> make it atomic, load once. 4. Stale GetBuffer/ReleaseBuffer pairing across a toggle -> epoch-stamp the GetBuffer and only capture in the same hooked epoch. 5. COM-object churn: re-creating the probe client every enable raced AudioSes -> build the probe once, keep it across toggles (only swap vtable slots); release on detach (shutdown_audio_hooks). Plus drain in-flight detours before tearing down state. Stress test: 0 crashes in many repeated runs (was ~50%). Guessed streams now echo (the no-echo path is reached via an exact/auto-attach format or override). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -252,7 +252,7 @@ BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved)
|
||||
coop::hook::set_log_ring(nullptr);
|
||||
coop::hook::remove_focus_spoof();
|
||||
coop::hook::remove_xinput_hooks();
|
||||
coop::hook::remove_audio_hooks();
|
||||
coop::hook::shutdown_audio_hooks(); // detach: remove detours + release the kept probe
|
||||
coop::hook::remove_present_hooks();
|
||||
coop::hook::remove_opengl_hooks();
|
||||
coop::hook::remove_mkb_hooks();
|
||||
|
||||
Reference in New Issue
Block a user