On 2/14/08, Michael Broughton <Michael_Broughton at advanis.ca> wrote: > > Although, hmmm.. thinking about it again, if we implement call locking > > in on_dtmf() callback, actually we will get into deadlock, as media > > transport mutex is not included in the standard lock order! > > Correct, but I was thinking that the timeout in acquire_call would allow > for a graceful failure (soft deadlock). I suppose it isn't a big deal if > a DTMF event is dropped while you are trying to shutdown the stream. > I think you're probably right, the callback thread would eventually timeout when it tries to call acquire_call(). The scenario would be like this: transport thread: 1. on_dtmf callback is called (with ioqueue's key mutex held) 2. tries to lock call with acquire_call() Application thread: 3. acquire_call() returns successfully 4. close transport, which eventually try to get ioqueue's key mutex This is a deadlock scenario. But with soft deadlock protection, step no 2 above would time out eventually, and everything will run again. But soft deadlocking is very expensive in term of processing, as everything that tries to lock PJSUA-LIB will be blocked while PJSUA-LIB tries to acquire (and finally gives up) the locks. This would block the application for at least 1 second for the best case, I think. > For my application, I think it is necessary because I need to manipulate > the call from the DTMF callback. I don't think handling the DTMF events > asynchronously will be responsive enough, and may cause other timing > issues with my application. > What about if you only post the destroy request to other thread, and handle everything else in the callback? Anyway the deadlock situation should only occur when we're trying to destroy the transport, so for everything else, it should be safe to process the call (and call acquire_call()) in the callback. cheers, -benny