I'm seeing what appears to be the same problem.
For me, the problem occurs when an RCF (2.0.1.101) client makes a synchronous call to the server which times out after connecting (see onConnectCompleted in the stack trace). In RCF::ClientStub::beginSend(), `timeoutMs' is computed by a call to `generateTimeoutMs(mEndTimeMs)'.
If the timeout has expired, this returns 0, and this zero is passed to RCF::ConnectionOrientedClientTransport::send, where the code incorrectly assumes that the value zero indicates an asynchronous call.
Here are the relevant lines of a stack trace of a `ping()':
Code: Select all
RCF::AssertFunctor::~AssertFunctor(this=0x0000700000cd9928) + 344 at Assert.hpp:90
RCF::VariableArgMacro<RCF::AssertFunctor>::~VariableArgMacro(this=0x0000700000cd9928) + 21 at Assert.hpp:131
RCF::VariableArgMacro<RCF::AssertFunctor>::~VariableArgMacro(this=0x0000700000cd9928) + 21 at Assert.hpp:131
RCF::ConnectionOrientedClientTransport::send(this=0x00007ff240e31560, clientStub=0x00007ff244892c00, data=0x00007ff244893160, totalTimeoutMs=0) + 696 at ConnectionOrientedClientTransport.cpp:366
RCF::ClientStub::beginSend(this=0x00007ff244892c00) + 1207 at Marshal.cpp:364
RCF::ClientStub::onRequestTransportFiltersCompleted(this=0x00007ff244892c00) + 1011 at Marshal.cpp:310
RCF::ClientStub::onConnectCompleted(this=0x00007ff244892c00, alreadyConnected=false) + 1216 at Marshal.cpp:422
RCF::TcpClientTransport::implConnect(this=0x00007ff240e31560, clientStub=0x00007ff244892c00, timeoutMs=2000) + 3605 at TcpClientTransport.cpp:168
RCF::ConnectionOrientedClientTransport::connect(this=0x00007ff240e31560, clientStub=0x00007ff244892c00, timeoutMs=2000) + 118 at ConnectionOrientedClientTransport.cpp:193
RCF::ClientStub::connect(this=0x00007ff244892c00) + 910 at Marshal.cpp:197
RCF::ClientStub::beginCall(this=0x00007ff244892c00) + 811 at Marshal.cpp:492
RCF::ClientStub::call(this=0x00007ff244892c00, rcs=Twoway) + 248 at Marshal.cpp:809
RCF::FutureImplBase::callSync(this=0x0000700000cdabd8) const + 378 at Future.cpp:110
RCF::FutureImplBase::call(this=0x0000700000cdabd8) const + 121 at Future.cpp:90
RCF::FutureImpl<RCF::Void>::~FutureImpl(this=0x0000700000cdabd8) + 38 at Future.hpp:349
RCF::FutureImpl<RCF::Void>::~FutureImpl(this=0x0000700000cdabd8) + 21 at Future.hpp:346
Here's where the timeout is computed:
Code: Select all
void ClientStub::beginSend()
{
//...
unsigned int timeoutMs = generateTimeoutMs(mEndTimeMs);
//...
int err = getTransport().send(*this, mEncodedByteBuffers, timeoutMs);
//...
}
Here's _how_ the timeout is computed:
Code: Select all
// Generate a timeout value for the given ending time.
// Returns zero if endTime <= current time <= endTime+10% of timer resolution,
// otherwise returns a nonzero duration in ms.
// Timer resolution as above (49 days).
boost::uint32_t generateTimeoutMs(unsigned int endTimeMs)
{
// 90% of the timer interval
boost::uint32_t currentTimeMs = getCurrentTimeMs();
boost::uint32_t timeoutMs = endTimeMs - currentTimeMs;
return (timeoutMs <= MaxTimeoutMs) ? timeoutMs : 0;
}
Finally, here's how `ConnectionOrientedClientTransport::send' _uses_ the timeout.
When too much time has elapsed, totalTimeoutMs will be zero, causing this code
to assume incorrectly that the call was asynchronous.
Code: Select all
if (totalTimeoutMs)
{
unsigned int startTimeMs = getCurrentTimeMs();
mEndTimeMs = startTimeMs + totalTimeoutMs;
mNoTimeout = false;
}
else
{
RCF_ASSERT(mAsync);