Okay, I've found the bug. It's a wrap around issue.
void ConnectionImpl::addSession(const boost::shared_ptr<SessionImpl>& session,
uint16_t channel)
{
Mutex::ScopedLock l(lock);
session->setChannel(channel ? channel : nextChannel++);
boost::weak_ptr<SessionImpl>& s = sessions[session->getChannel()];
boost::shared_ptr<SessionImpl> ss = s.lock();
if (ss) {
throw SessionBusyException(QPID_MSG("Channel " <<
ss->getChannel() << " attached to " << ss->getId()));
}
s = session;
}
At the time of the error this is the value of some of the variables:
channel = 0
nextChannel = 3
session->getChannel() = 2
sessions [6]((0,{px=0x083c8508 pn={...} }),(1,{px=0x0839b7a8 pn={...}
}),(2,{px=0x033f3bb0 pn={...} }),(65533,{px=0x083c2008 pn={...}
}),(65534,{px=0x08394c00 pn={...} }),(65535,{px=0x083cd368 pn={...} }))
Note how channel 2 is actually already in use! That should not be as
our nextChannel integer should point at a free channel. Sadly that is
try until nextChannel wraps around, which will happen eventually, just
in my program is ends up being sooner rather than later. I've
rewritten part addSession.
void ConnectionImpl::addSession(const boost::shared_ptr<SessionImpl>& session,
uint16_t channel)
{
Mutex::ScopedLock l(lock);
if ( channel == 0 )
{
for (uint16_t c = nextChannel; c != (nextChannel-1); c++ )
{
boost::weak_ptr<SessionImpl>& s = sessions[c];
boost::shared_ptr<SessionImpl> ss = s.lock();
if ( !ss )
{
session->setChannel(c);
nextChannel = c + 1;
s = session;
return;
}
}
throw SessionBusyException(QPID_MSG("All channels in use"));
}
else
{
session->setChannel(channel);
boost::weak_ptr<SessionImpl>& s =
sessions[session->getChannel()];
boost::shared_ptr<SessionImpl> ss = s.lock();
if (ss) throw SessionBusyException(QPID_MSG("Channel " <<
ss->getChannel() << " attached to " << ss->getId()));
s = session;
}
}
I'll submit a bug report as well.
- Ron
> Guys,
> I've been using QPID successfully for a few months now, however once
> in a while my program terminates with this exception:
> terminate called after throwing an instance of
> 'qpid::framing::SessionBusyException'
> what(): session-busy: Channel 3 attached to
> guest.50e08be0-d1f6-4c43-8b81-cd782838d6be
> (qpid/client/ConnectionImpl.cpp:98)
> terminate called after throwing an instance of
> 'qpid::framing::SessionBusyException'
> what(): session-busy: Channel 2 attached to
> guest.b2a5593f-6692-425d-a0a4-f123bb679935
> (qpid/client/ConnectionImpl.cpp:98)
> I'm sure I'm doing something wrong here, can anyone point me in the
> right direction?
> My application works as follows.
> One FailoverManager.
> failoverManager->execute( ... );
> is called from different threads, no mutex here.
> I have two flavors of FailoverManager::Commands that are passed to
> the FailOverManager:
> 1. Sending single Topic messages. (These happen all the time from
> different threads)
> 2. Listening for a list of Topic messages, using the
> SubscriptionManager
> (this list is mutex protected, and typically doesn't change
> during runtime of the application unless someone is changing the
> configuration, this was not the case during the crashes)
> Sadly the minidumps I have are on Linux AMD64 using breakpad, for
> which the stack walker is not yet done and hence I can't see where
> the crash originated.
> Thanks,
> Ron
> ---------------------------------------------------------------------
> Apache Qpid - AMQP Messaging Implementation
> Project: http://qpid.apache.org
> Use/Interact: mailto:[email protected]
---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project: http://qpid.apache.org
Use/Interact: mailto:[email protected]