Take a look to my proposition (a bit draft variant but in anyway) - in worst case (if not able to Lock the mutexes) we only lost the real reason (why does it fails) and return EndedByCallerAbort.
// Do the transport connect
connectionState = AwaitingTransportConnect;
// Release the mutex as can deadlock trying to clear call during connect.
Unlock();
PBoolean connectFailed = false;
if (!signallingChannel->IsOpen()) {
signallingChannel->SetWriteTimeout(100);
connectFailed = !signallingChannel->Connect();
}
// See if transport connect failed, abort if so.
if (connectFailed) {
connectionState = NoConnectionActive;
switch (signallingChannel->GetErrorNumber()) {
case ENETUNREACH :
reason = EndedByUnreachable;
break;
case ECONNREFUSED :
reason = EndedByNoEndPoint;
break;
case ETIMEDOUT :
reason = EndedByHostOffline;
break;
default:
reason = EndedByConnectFail;
}
}
}
// Lock while checking for shutting down.
if (!Lock())
return EndedByCallerAbort;
//...
Iurii Gordiienko
--- Original message ---
From: "Jan Willamowius" <jan@willamowius.de>
Date: 27 December 2015, 19:47:21
Hi Iurii,
PTLib 2.10.x and 2.11.x have a method to check, if a mutex is already
locked, but they changed the API and from 2.12.x on there is no way to
check except to try to lock it.
Replace H323Connection::Unlock() in src/h323.cxx with this version:
void H323Connection::Unlock()
{
// calling Signal() on a mutex that isn't locked is causing an assert,
// so we make sure it is locked before the Signal()
innerMutex.Wait(0);
innerMutex.Signal();
outerMutex.Wait(0);
outerMutex.Signal();
}
Please try the change and report back how it works.
Then I'll commit the code to the CVS.
Regards,
Jan
--
Jan Willamowius, Founder of the GNU Gatekeeper Project
EMail : jan@willamowius.de
Website: http://www.gnugk.org
Support: http://www.willamowius.com/gnugk-support.html
Relaxed Communications GmbH
Frahmredder 91
22393 Hamburg
Geschäftsführer: Jan Willamowius
HRB 125261 (Amtsgericht Hamburg)
USt-IdNr: DE286003584
Iurii Gordiienko wrote:
> Hi,
> I have found a bug with twice H323Connection::Unlock() call if we have an connection issue.
> Take a look:
> 1.We are running connection.SendSignalSetup function from H225CallThread::Main() and if it returns any reason!=H323Connection::EndedByCallerAbort we will Unlock the connection.
>
> void H225CallThread::Main() { PTRACE(3, "H225\tStarted call thread");
> if (connection.Lock()) { H323Connection::CallEndReason reason = connection.SendSignalSetup(alias, address);
> // Special case, if we aborted the call then already will be unlocked if (reason != H323Connection::EndedByCallerAbort) connection.Unlock();
> // bla-bla-bla }
>
> 2.But we have case when connection.SendSignalSetup returns non H323Connection::EndedByCallerAbort reason but has own unlocked state - for this case PTLIB will unlock the mutex twice with assert (as minimum) message.
> H323Connection::SendSignalSetup(const PString & alias,
> const H323TransportAddress & address) { //bla-bla-bla
> // Release the mutex as can deadlock trying to clear call during connect. Unlock();
> PBoolean connectFailed = false; if (!signallingChannel->IsOpen()) { signallingChannel->SetWriteTimeout(100); connectFailed = !signallingChannel->Connect(); }
> // See if transport connect failed, abort if so. if (connectFailed) { connectionState = NoConnectionActive; switch (signallingChannel->GetErrorNumber()) { case ENETUNREACH : return EndedByUnreachable; case ECONNREFUSED : return EndedByNoEndPoint; case ETIMEDOUT : return EndedByHostOffline; } return EndedByConnectFail; }
> }
> Thanks -- Iurii Gordiienko