Anton Baskanov : quartz: Use a separate critical section for events.

Alexandre Julliard julliard at winehq.org
Mon Apr 12 16:11:24 CDT 2021


Module: wine
Branch: master
Commit: 86cbfa4bea7199ffa1507420b7f5b1f3c3a70a77
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=86cbfa4bea7199ffa1507420b7f5b1f3c3a70a77

Author: Anton Baskanov <baskanov at gmail.com>
Date:   Sat Apr 10 11:45:35 2021 -0500

quartz: Use a separate critical section for events.

This undoes dc836b85c1458c916c5ad3b86ff8df59ce634dd9.

Signed-off-by: Anton Baskanov <baskanov at gmail.com>
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/quartz/filtergraph.c | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index a8c6cc3391c..825bef9e12e 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -104,6 +104,11 @@ struct filter_graph
     IReferenceClock *refClock;
     IBaseFilter *refClockProvider;
 
+    /* We may indirectly wait for streaming threads while holding graph->cs in
+     * IMediaFilter::Stop() or IMediaSeeking::SetPositions(). Since streaming
+     * threads call IMediaEventSink::Notify() to queue EC_COMPLETE, we must
+     * use a separate lock to avoid them deadlocking on graph->cs. */
+    CRITICAL_SECTION event_cs;
     struct list media_events;
     HANDLE media_event_handle;
     HWND media_event_window;
@@ -116,6 +121,8 @@ struct filter_graph
     int HandleEcComplete;
     int HandleEcRepaint;
     int HandleEcClockChanged;
+    unsigned int got_ec_complete : 1;
+    unsigned int media_events_disabled : 1;
 
     CRITICAL_SECTION cs;
     ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
@@ -135,8 +142,6 @@ struct filter_graph
     LONGLONG current_pos;
 
     unsigned int needs_async_run : 1;
-    unsigned int got_ec_complete : 1;
-    unsigned int media_events_disabled : 1;
 };
 
 struct enum_filters
@@ -467,6 +472,7 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
             CloseHandle(This->message_thread);
             CloseHandle(This->message_thread_ret);
         }
+        DeleteCriticalSection(&This->event_cs);
 	DeleteCriticalSection(&This->cs);
         free(This);
 
@@ -1695,8 +1701,10 @@ static HRESULT graph_start(struct filter_graph *graph, REFERENCE_TIME stream_sta
     struct filter *filter;
     HRESULT hr = S_OK;
 
+    EnterCriticalSection(&graph->event_cs);
     graph->EcCompleteCount = 0;
     update_render_count(graph);
+    LeaveCriticalSection(&graph->event_cs);
 
     LIST_FOR_EACH_ENTRY_SAFE(event, next, &graph->media_events, struct media_event, entry)
     {
@@ -1813,7 +1821,10 @@ static HRESULT WINAPI MediaControl_Run(IMediaControl *iface)
     }
 
     sort_filters(graph);
+
+    EnterCriticalSection(&graph->event_cs);
     update_render_count(graph);
+    LeaveCriticalSection(&graph->event_cs);
 
     if (graph->state == State_Stopped)
     {
@@ -4752,12 +4763,12 @@ static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *code,
     if (WaitForSingleObject(graph->media_event_handle, timeout))
         return E_ABORT;
 
-    EnterCriticalSection(&graph->cs);
+    EnterCriticalSection(&graph->event_cs);
 
     if (!(entry = list_head(&graph->media_events)))
     {
         ResetEvent(graph->media_event_handle);
-        LeaveCriticalSection(&graph->cs);
+        LeaveCriticalSection(&graph->event_cs);
         return E_ABORT;
     }
     event = LIST_ENTRY(entry, struct media_event, entry);
@@ -4767,7 +4778,7 @@ static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *code,
     *param2 = event->param2;
     free(event);
 
-    LeaveCriticalSection(&graph->cs);
+    LeaveCriticalSection(&graph->event_cs);
     return S_OK;
 }
 
@@ -5015,7 +5026,10 @@ static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
     }
 
     sort_filters(graph);
+
+    EnterCriticalSection(&graph->event_cs);
     update_render_count(graph);
+    LeaveCriticalSection(&graph->event_cs);
 
     if (graph->defaultclock && !graph->refClock)
         IFilterGraph2_SetDefaultSyncSource(&graph->IFilterGraph2_iface);
@@ -5261,7 +5275,7 @@ static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG code,
 
     TRACE("graph %p, code %#x, param1 %#Ix, param2 %#Ix.\n", graph, code, param1, param2);
 
-    EnterCriticalSection(&graph->cs);
+    EnterCriticalSection(&graph->event_cs);
 
     if (code == EC_COMPLETE && graph->HandleEcComplete)
     {
@@ -5285,7 +5299,7 @@ static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG code,
         queue_media_event(graph, code, param1, param2);
     }
 
-    LeaveCriticalSection(&graph->cs);
+    LeaveCriticalSection(&graph->event_cs);
     return S_OK;
 }
 
@@ -5591,6 +5605,8 @@ static HRESULT filter_graph_common_create(IUnknown *outer, IUnknown **out, BOOL
 
     InitializeCriticalSection(&object->cs);
     object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": filter_graph.cs");
+    InitializeCriticalSection(&object->event_cs);
+    object->event_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": filter_graph.event_cs");
 
     object->defaultclock = TRUE;
 




More information about the wine-cvs mailing list