DirectShow and the real deadlocks (continued)
- From: "Cyril" <Cyril@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Wed, 4 May 2005 11:16:02 -0700
Hi,
While playing with the source push filters, I've identified a deadlock.
So let me explain what I'm doing (maybe I'm doing it wrong).
I've used the pushsource sample from the directshow sdk. As I've already
mentionned, in that post :
http://msdn.microsoft.com/newsgroups/default.aspx?dg=microsoft.public.win32.programmer.directx.video&tid=c8bcae56-ca70-4d31-863a-9d5ddf7dcd9e&cat=en-us-msdn&lang=en&cr=US&sloc=en-us&m=1&p=1
The application is going to deadlock if you lock the filter's lock in the
FillBuffer method.
I'm not doing this in my code anymore.
This is what happens (I've simplified the case) :
There is 2 threads running in the application while the graph is running :
1) The Main Thread (which is pumping its windows messages)
2) The worker thread (instanciated as the CAMThread base of CSourceStream)
which calls MyOutputPin::FillBuffer and CBaseOutputPin::Deliver (and some
other methods too, but we don't care)
Now, when the user is leaving, the main thread asks the graph to stop (by
calling the IMediaControl::Stop method). For simplicity let's say that the
graph is compound of only 2 filters (Renderer + Source). The graph first
stops the renderer, as stated here :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/streamingthreadandapplicationthread.asp
Before the renderer filters stop entirely (whatever it is doing), a thread
context switch occurs. The FillBuffer method is called, and it is running
entirely and returns S_OK. Then because FillBuffer returns S_OK (and in the
current CSourceStream implementation), the class then call
CBaseOutputPin::Deliver, which in turn, calls m_pInputPin->Receive (and
m_pInputPin is the input pin of the Renderer).
The execution then stops (deadlock). I don't know what is the done in the
new renderer (I'm using VMR9) in the Receive method when the graph already
told the renderer to stop but I am experiencing deadlock.
What I'm seeing in the SDK class I have:
In RenBase.cpp, CBaseRenderer::Stop starts by locking the InterfaceLock,
and ends by waiting in CBaseRenderer::WaitForReceiveToComplete for
m_bInReceive to become FALSE. InterfaceLock is still hold while waiting
(because it is still in the scope when calling WaitForReceiveToComplete). The
main thread is waiting here in the previous example.
At the same time, in the worker thread, the CRendererInputPin::Receive
method is called, which in turn always calls the CBaseRenderer::Receive,
which always calls CBaseRenderer::PrepareReceive. In
CBaseRenderer::PrepareReceive, the first line is trying to lock the
InterfaceLock which is hold by the main thread in CBaseRenderer::Stop.
We have a deadlock here.
In usual situations, the PrepareReceive locks the InterfaceLock and then
resets the m_bInReceive to FALSE, so that the renderer can stop waiting, and
leave.
The good solution to this issue, is to move the WaitForReceiveToComplete
call outside the scope of InterfaceLock locking, as WaitForReceiveToComplete
doesn't modify any members, hence doesn't require locking.
What could be a possible workaround for WMR9 (I don't have the source code,
but because I'm having similar issues, I guess it is also there) ?
I've thought of overloading the Deliver method, to call the
RendererInputPin::Receive only if the graph is still running.
But there is no way to make this atomically (check is the graph is running
and call the receive method then). So, if a context switch happens between
the test and the call, we are dead.
The only solution I've seen so far would be to add a proprietary interface
to my source filter, to set an "Terminate" event that FillBuffer would wait
for, and if set, FillBuffer would set a answering event
"OkImReturningFalseToCloseTheStream" (and return false to tell the worker
thread that it is the end of the stream) that the main thread would wait for,
before calling the IMediaControl::Stop method.
I'm sure there is a better way for doing this, so I guess I don't find the
right documentation.
Sincerely,
Cyril
.
- Follow-Ups:
- Prev by Date: YV12 question
- Next by Date: Re: Run my graph kills the video window ??
- Previous by thread: YV12 question
- Next by thread: RE: DirectShow and the real deadlocks (continued)
- Index(es):
Relevant Pages
|