openh323 thread synchronization problem in RAS protocol which crashed app
Change Desc.: Fixed thread synchronization problem in H323Transactor, requestsMutex now extended over Poll() and MakeRequest() function:
BOOL H323Transactor::MakeRequest(Request & request)
{
PTRACE(3, "Trans\tMaking request: " << request.requestPDU.GetChoice().GetTagName());
OnSendingPDU(request.requestPDU.GetPDU());
requestsMutex.Wait();
requests.SetAt(request.sequenceNumber, &request);
requestsMutex.Signal();
BOOL ok = request.Poll(*this);
// requestsMutex.Wait(); // FIX
requests.SetAt(request.sequenceNumber, NULL);
requestsMutex.Signal();
return ok;
}
BOOL H323Transactor::Request::Poll(H323Transactor & rasChannel)
{
H323EndPoint & endpoint = rasChannel.GetEndPoint();
responseResult = AwaitingResponse;
for (unsigned retry = 1; retry <= endpoint.GetRasRequestRetries(); retry++) {
// To avoid race condition with RIP must set timeout before sending the packet
whenResponseExpected = PTimer::Tick() + endpoint.GetRasRequestTimeout();
if (!rasChannel.WriteTo(requestPDU, requestAddresses, FALSE))
{
rasChannel.requestsMutex.Wait(); // FIX
break;
}
PTRACE(3, "Trans\tWaiting on response to seqnum=" << requestPDU.GetSequenceNumber()
<< " for " << setprecision(1) << endpoint.GetRasRequestTimeout() << " seconds");
do {
// Wait for a response
responseHandled.Wait(whenResponseExpected - PTimer::Tick());
rasChannel.requestsMutex.Wait(); // FIX
PWaitAndSignal mutex(responseMutex); // Wait till lastRequest goes out of scope
switch (responseResult) {
case AwaitingResponse : // Was a timeout
responseResult = NoResponseReceived;
break;
case ConfirmReceived :
return TRUE;
case RejectReceived :
return FALSE;
case BadCryptoTokens :
PTRACE(2, "Trans\tResponse to seqnum=" << requestPDU.GetSequenceNumber()
<< " had invalid crypto tokens.");
return FALSE;
default : // RequestInProgress
responseResult = AwaitingResponse; // Keep waiting
rasChannel.requestsMutex.Signal(); // FIX
break; // FIX
}
PTRACE_IF(3, responseResult == AwaitingResponse,
"Trans\tWaiting again on response to seqnum=" << requestPDU.GetSequenceNumber() <<
" for " << setprecision(1) << (whenResponseExpected - PTimer::Tick()) << " seconds");
} while (responseResult == AwaitingResponse);
PTRACE(1, "Trans\tTimeout on request seqnum=" << requestPDU.GetSequenceNumber()
<< ", try #" << retry << " of " << endpoint.GetRasRequestRetries());
}
PTRACE(1, "Trans\tPoll request ended with return value false");
return FALSE;
}
Logged In: YES
user_id=1929069
Originator: NO
bug/fix added by arimont