From: Brendan McGrath <bmcgrath@codeweavers.com> When SAR is the time source, the call to GetCorrelatedTime will result in an attempt to acquire SAR's critical section. This means this thread will hold the presentation clock critical section and then attempt to obtain SARs critical section. However, if SAR is in the process of shutdown in a parallel thread, then that thread will already hold the SAR critical section and call IMFPresentationClock::RemoveClockStateSink. This will attempt to acquire the presentation clock critical section. In other words, we have two threads trying to acquire the same two critical sections in the opposite order. The result is both threads waiting on the other and thus a deadlock. This commit resolves the deadlock by ensuring the presentation clock does not hold its own critical section when calling GetCorrelatedTime. --- dlls/mf/clock.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/dlls/mf/clock.c b/dlls/mf/clock.c index f1aead0fcb5..7cc0a328891 100644 --- a/dlls/mf/clock.c +++ b/dlls/mf/clock.c @@ -565,21 +565,28 @@ static struct clock_timer *presentation_clock_next_timer(struct presentation_clo static void CALLBACK presentation_clock_timer_callback(IUnknown *context) { struct presentation_clock *clock = impl_from_IMFPresentationClock((IMFPresentationClock*)context); + IMFPresentationTimeSource *time_source; struct clock_timer *timer; LONGLONG time, systime; - EnterCriticalSection(&clock->cs); - if (clock->time_source && - SUCCEEDED(IMFPresentationTimeSource_GetCorrelatedTime(clock->time_source, 0, &time, &systime))) + if ((time_source = clock->time_source)) + IMFPresentationTimeSource_AddRef(time_source); + + if (time_source && + SUCCEEDED(IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime))) { + EnterCriticalSection(&clock->cs); while ( (timer = presentation_clock_next_timer(clock, time)) ) { list_remove(&timer->entry); MFInvokeCallback(timer->result); IUnknown_Release(&timer->IUnknown_iface); } + LeaveCriticalSection(&clock->cs); } - LeaveCriticalSection(&clock->cs); + + if (time_source) + IMFPresentationTimeSource_Release(time_source); } static HRESULT clock_change_state(struct presentation_clock *clock, enum clock_command command, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10715