From: Conor McCarthy cmccarthy@codeweavers.com
The following sequence can occur: sink_EndOfStream lock stream_cs renderer sink_eos strmbase_passthrough_eos IMediaSeeking_GetStopPosition MediaSeekingPassThru_GetStopPosition get_connected IPin_ConnectedTo lock filter_cs
And at the same time: filter_Stop lock filter_cs dmo_wrapper_cleanup_stream lock stream_cs
Resulting in deadlock. --- dlls/qasf/dmowrapper.c | 4 ++-- dlls/quartz/avidec.c | 4 ++-- dlls/quartz/dsoundrender.c | 6 +++--- dlls/quartz/videorenderer.c | 12 ++++++------ dlls/quartz/vmr9.c | 6 +++--- dlls/winegstreamer/quartz_transform.c | 4 ++-- include/wine/strmbase.h | 1 - libs/strmbase/filter.c | 7 ------- libs/strmbase/pin.c | 8 ++++---- libs/strmbase/renderer.c | 8 ++++---- 10 files changed, 26 insertions(+), 34 deletions(-)
diff --git a/dlls/qasf/dmowrapper.c b/dlls/qasf/dmowrapper.c index f6e586d0235..75047ab9548 100644 --- a/dlls/qasf/dmowrapper.c +++ b/dlls/qasf/dmowrapper.c @@ -750,7 +750,7 @@ static HRESULT dmo_wrapper_cleanup_stream(struct strmbase_filter *iface)
IUnknown_QueryInterface(filter->dmo, &IID_IMediaObject, (void **)&dmo);
- EnterCriticalSection(&filter->filter.stream_cs); + EnterCriticalSection(&filter->filter.filter_cs); for (i = 0; i < filter->source_count; ++i) { if (filter->sources[i].pin.pin.peer) @@ -761,7 +761,7 @@ static HRESULT dmo_wrapper_cleanup_stream(struct strmbase_filter *iface) IMediaObject_FreeStreamingResources(dmo);
IMediaObject_Release(dmo); - LeaveCriticalSection(&filter->filter.stream_cs); + LeaveCriticalSection(&filter->filter.filter_cs); return S_OK; }
diff --git a/dlls/quartz/avidec.c b/dlls/quartz/avidec.c index 9f1a7db1586..a1bfb35861f 100644 --- a/dlls/quartz/avidec.c +++ b/dlls/quartz/avidec.c @@ -653,9 +653,9 @@ static HRESULT avi_decompressor_cleanup_stream(struct strmbase_filter *iface)
if (filter->hvid) { - EnterCriticalSection(&filter->filter.stream_cs); + EnterCriticalSection(&filter->filter.filter_cs); res = ICDecompressEnd(filter->hvid); - LeaveCriticalSection(&filter->filter.stream_cs); + LeaveCriticalSection(&filter->filter.filter_cs); if (res) { ERR("ICDecompressEnd() failed, error %Id.\n", res); diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c index 59609a3c849..9713ace16c9 100644 --- a/dlls/quartz/dsoundrender.c +++ b/dlls/quartz/dsoundrender.c @@ -543,7 +543,7 @@ static HRESULT dsound_render_sink_end_flush(struct strmbase_sink *iface) { struct dsound_render *filter = impl_from_strmbase_pin(&iface->pin);
- EnterCriticalSection(&filter->filter.stream_cs); + EnterCriticalSection(&filter->filter.filter_cs); if (filter->eos && filter->filter.state != State_Stopped) { WaitForSingleObject(filter->render_thread, INFINITE); @@ -551,7 +551,7 @@ static HRESULT dsound_render_sink_end_flush(struct strmbase_sink *iface)
if (!(filter->render_thread = CreateThread(NULL, 0, render_thread_run, filter, 0, NULL))) { - LeaveCriticalSection(&filter->filter.stream_cs); + LeaveCriticalSection(&filter->filter.filter_cs); return HRESULT_FROM_WIN32(GetLastError()); } filter->eos = FALSE; @@ -571,7 +571,7 @@ static HRESULT dsound_render_sink_end_flush(struct strmbase_sink *iface) filter->writepos = filter->buf_size; }
- LeaveCriticalSection(&filter->filter.stream_cs); + LeaveCriticalSection(&filter->filter.filter_cs); return S_OK; }
diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c index bbd34678dfd..7d09046101c 100644 --- a/dlls/quartz/videorenderer.c +++ b/dlls/quartz/videorenderer.c @@ -225,33 +225,33 @@ static HRESULT video_renderer_get_current_image(struct video_window *iface, LONG size_t image_size; BYTE *sample_data;
- EnterCriticalSection(&filter->renderer.filter.stream_cs); + EnterCriticalSection(&filter->renderer.filter.filter_cs);
bih = get_bitmap_header(&filter->renderer.sink.pin.mt); image_size = bih->biWidth * bih->biHeight * bih->biBitCount / 8;
if (!image) { - LeaveCriticalSection(&filter->renderer.filter.stream_cs); + LeaveCriticalSection(&filter->renderer.filter.filter_cs); *size = sizeof(BITMAPINFOHEADER) + image_size; return S_OK; }
if (filter->renderer.filter.state != State_Paused) { - LeaveCriticalSection(&filter->renderer.filter.stream_cs); + LeaveCriticalSection(&filter->renderer.filter.filter_cs); return VFW_E_NOT_PAUSED; }
if (!filter->renderer.current_sample) { - LeaveCriticalSection(&filter->renderer.filter.stream_cs); + LeaveCriticalSection(&filter->renderer.filter.filter_cs); return E_UNEXPECTED; }
if (*size < sizeof(BITMAPINFOHEADER) + image_size) { - LeaveCriticalSection(&filter->renderer.filter.stream_cs); + LeaveCriticalSection(&filter->renderer.filter.filter_cs); return E_OUTOFMEMORY; }
@@ -259,7 +259,7 @@ static HRESULT video_renderer_get_current_image(struct video_window *iface, LONG IMediaSample_GetPointer(filter->renderer.current_sample, &sample_data); memcpy((char *)image + sizeof(BITMAPINFOHEADER), sample_data, image_size);
- LeaveCriticalSection(&filter->renderer.filter.stream_cs); + LeaveCriticalSection(&filter->renderer.filter.filter_cs); return S_OK; }
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c index 611a1256b0e..d75b7085602 100644 --- a/dlls/quartz/vmr9.c +++ b/dlls/quartz/vmr9.c @@ -635,7 +635,7 @@ static HRESULT vmr_get_current_image(struct video_window *iface, LONG *size, LON char *dst; HRESULT hr;
- EnterCriticalSection(&filter->renderer.filter.stream_cs); + EnterCriticalSection(&filter->renderer.filter.filter_cs); device = filter->allocator_d3d9_dev;
bih = *get_filter_bitmap_header(filter); @@ -644,7 +644,7 @@ static HRESULT vmr_get_current_image(struct video_window *iface, LONG *size, LON if (!image) { *size = sizeof(BITMAPINFOHEADER) + bih.biSizeImage; - LeaveCriticalSection(&filter->renderer.filter.stream_cs); + LeaveCriticalSection(&filter->renderer.filter.filter_cs); return S_OK; }
@@ -680,7 +680,7 @@ static HRESULT vmr_get_current_image(struct video_window *iface, LONG *size, LON out: if (surface) IDirect3DSurface9_Release(surface); if (rt) IDirect3DSurface9_Release(rt); - LeaveCriticalSection(&filter->renderer.filter.stream_cs); + LeaveCriticalSection(&filter->renderer.filter.filter_cs); return hr; }
diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c index ff57ea02ed0..69b84c66a49 100644 --- a/dlls/winegstreamer/quartz_transform.c +++ b/dlls/winegstreamer/quartz_transform.c @@ -129,10 +129,10 @@ static HRESULT transform_cleanup_stream(struct strmbase_filter *iface) { IMemAllocator_Decommit(filter->source.pAllocator);
- EnterCriticalSection(&filter->filter.stream_cs); + EnterCriticalSection(&filter->filter.filter_cs); wg_transform_destroy(filter->transform); wg_sample_queue_destroy(filter->sample_queue); - LeaveCriticalSection(&filter->filter.stream_cs); + LeaveCriticalSection(&filter->filter.filter_cs); }
return S_OK; diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h index 978d1c67160..b44277ed25d 100644 --- a/include/wine/strmbase.h +++ b/include/wine/strmbase.h @@ -146,7 +146,6 @@ struct strmbase_filter IUnknown *outer_unk; LONG refcount; CRITICAL_SECTION filter_cs; - CRITICAL_SECTION stream_cs;
FILTER_STATE state; IReferenceClock *clock; diff --git a/libs/strmbase/filter.c b/libs/strmbase/filter.c index 3229c7ba82a..fe6f3cd7215 100644 --- a/libs/strmbase/filter.c +++ b/libs/strmbase/filter.c @@ -528,10 +528,6 @@ void strmbase_filter_init(struct strmbase_filter *filter, IUnknown *outer, InitializeCriticalSection(&filter->filter_cs); if (filter->filter_cs.DebugInfo != (RTL_CRITICAL_SECTION_DEBUG *)-1) filter->filter_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": strmbase_filter.filter_cs"); - if (!InitializeCriticalSectionEx(&filter->stream_cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO)) - InitializeCriticalSection(&filter->stream_cs); - if (filter->stream_cs.DebugInfo != (RTL_CRITICAL_SECTION_DEBUG *)-1) - filter->stream_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": strmbase_filter.stream_cs"); filter->clsid = *clsid; filter->pin_version = 1; filter->ops = ops; @@ -546,7 +542,4 @@ void strmbase_filter_cleanup(struct strmbase_filter *filter) if (filter->filter_cs.DebugInfo != (RTL_CRITICAL_SECTION_DEBUG *)-1) filter->filter_cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&filter->filter_cs); - if (filter->stream_cs.DebugInfo != (RTL_CRITICAL_SECTION_DEBUG *)-1) - filter->stream_cs.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&filter->stream_cs); } diff --git a/libs/strmbase/pin.c b/libs/strmbase/pin.c index 03330837477..b47b836c872 100644 --- a/libs/strmbase/pin.c +++ b/libs/strmbase/pin.c @@ -909,9 +909,9 @@ static HRESULT WINAPI sink_EndOfStream(IPin *iface)
if (pin->pFuncsTable->sink_eos) { - EnterCriticalSection(&pin->pin.filter->stream_cs); + EnterCriticalSection(&pin->pin.filter->filter_cs); hr = pin->pFuncsTable->sink_eos(pin); - LeaveCriticalSection(&pin->pin.filter->stream_cs); + LeaveCriticalSection(&pin->pin.filter->filter_cs); return hr; }
@@ -1122,9 +1122,9 @@ static HRESULT WINAPI MemInputPin_Receive(IMemInputPin *iface, IMediaSample *sam
if (pin->pFuncsTable->pfnReceive) { - EnterCriticalSection(&pin->pin.filter->stream_cs); + EnterCriticalSection(&pin->pin.filter->filter_cs); hr = pin->pFuncsTable->pfnReceive(pin, sample); - LeaveCriticalSection(&pin->pin.filter->stream_cs); + LeaveCriticalSection(&pin->pin.filter->filter_cs); } return hr; } diff --git a/libs/strmbase/renderer.c b/libs/strmbase/renderer.c index dc421f499ed..66d0e5cc7af 100644 --- a/libs/strmbase/renderer.c +++ b/libs/strmbase/renderer.c @@ -373,9 +373,9 @@ static HRESULT WINAPI BaseRenderer_Receive(struct strmbase_sink *pin, IMediaSamp hr = filter->ops->renderer_render(filter, sample);
SetEvent(filter->state_event); - LeaveCriticalSection(&filter->filter.stream_cs); + LeaveCriticalSection(&filter->filter.filter_cs); WaitForMultipleObjects(2, events, FALSE, INFINITE); - EnterCriticalSection(&filter->filter.stream_cs); + EnterCriticalSection(&filter->filter.filter_cs);
filter->current_sample = NULL; } @@ -475,14 +475,14 @@ static HRESULT sink_end_flush(struct strmbase_sink *iface) { struct strmbase_renderer *filter = impl_from_IPin(&iface->pin.IPin_iface);
- EnterCriticalSection(&filter->filter.stream_cs); + EnterCriticalSection(&filter->filter.filter_cs);
filter->eos = FALSE; reset_qos(filter); strmbase_passthrough_invalidate_time(&filter->passthrough); ResetEvent(filter->flush_event);
- LeaveCriticalSection(&filter->filter.stream_cs); + LeaveCriticalSection(&filter->filter.filter_cs); return S_OK; }