Recover the video mirror from a WAIT_ABANDONED keyed mutex

SharedTextureSource::update() acquired the shared-texture keyed mutex with
`AcquireSync(...) == S_OK`. But WAIT_ABANDONED -- a prior owner (e.g. a host that
crashed mid-acquire, then reconnected) died holding it -- actually GRANTS us
ownership. Treating it as failure skipped the copy AND never released, so the
next AcquireSync blocked forever and the mirror froze permanently after a crash
+ reconnect (directly relevant to the new reconnect path).

Factor the decision into keyed_mutex_acquired(HRESULT) (capture/keyed_mutex.hpp):
S_OK or WAIT_ABANDONED -> copy + release; timeout/hard errors -> skip the frame.
update() now uses it.

Test-first: keyed_mutex_test asserts WAIT_ABANDONED is treated as acquired while
the genuine "didn't get it" cases (timeout, E_FAIL, device-removed) are not. The
full cross-process abandonment is keyed-mutex OS semantics, not re-tested with a
child process here -- the predicate is the regression surface.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 01:12:29 +02:00
parent 8182389091
commit bdb700ec56
5 changed files with 75 additions and 6 deletions

View File

@@ -173,6 +173,12 @@ add_executable(srgb_format_test srgb_format_test.cpp)
target_include_directories(srgb_format_test PRIVATE ${CMAKE_SOURCE_DIR}/host/src)
add_test(NAME srgb_format_test COMMAND srgb_format_test)
# Unit test for the keyed-mutex acquire decision (capture/keyed_mutex.hpp): WAIT_ABANDONED must be
# treated as "acquired" so a mirror recovers after a host crash instead of freezing. Header-only.
add_executable(keyed_mutex_test keyed_mutex_test.cpp)
target_include_directories(keyed_mutex_test PRIVATE ${CMAKE_SOURCE_DIR}/host/src)
add_test(NAME keyed_mutex_test COMMAND keyed_mutex_test)
# In-process self-test for the Present-hook video path. Reuses the shipping
# present_hook.cpp and drives a real D3D11 swapchain in the same process, so it
# exercises the IDXGISwapChain::Present inline hook, the shared keyed-mutex
@@ -311,6 +317,7 @@ coop_output_subdir(tests
dinput_hook_test
audio_ring_test
ipc_server_test
keyed_mutex_test
detour_gate_test
hook_install_test
mkb_ring_test