You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@qpid.apache.org by Rob Springer <rs...@etinternational.com> on 2009/03/03 23:27:38 UTC

Potential deadlock with LocalQueue::get() / Session::close()?

Hey all - I've noticed a problem when debugging some code, and it looks
to my eyes like there's a potential deadlock situation using the timed
LocalQueue::get() command when a fatal interrupt occurs.  I've posted
what I hope is clear reproducer code below.  Could someone else take a
quick look at it and tell me if I'm crazy or correct?  The long and the
short of it looks to be that, when a timed LocalQueue::get() is called,
a particular mutex is held.  When the flow of execution is altered by an
interrupt, if Session::close() is called (in, say, a cleanup routine),
that mutex need to again be held, but since it is already being held, a
deadlock occurs.

Really, I assume the "no-deadlock" case is just as susceptible, but the
dangerous window is just smaller.  Is there a workaround to force an
unlock?

Thanks for the help!
-rob

#include <iostream>
#include <string>
#include <qpid/client/Connection.h>
#include <qpid/client/Session.h>
#include <qpid/client/SubscriptionManager.h>
#include <qpid/client/Subscription.h>
#include <qpid/client/LocalQueue.h>
#include <qpid/client/Message.h>
#include <signal.h>

using namespace qpid;
using namespace client;

Session* globalSession = NULL;

void intHandler(int signum)
{
    std::cout << "IN INTERRUPT HANDLER" << std::endl;
    if(globalSession)
        globalSession->close();
    std::cout << "SESSION CLOSED" << std::endl;
    exit(0);
}

int main(int argc, char** argv)
{
    signal(SIGINT, intHandler);
    Connection conn;
    conn.open("localhost", 5672);
    Session session = conn.newSession();
    globalSession = &session;
    SubscriptionManager subMgr(session);
    session.queueDeclare(arg::queue="asdf");
    session.exchangeBind(arg::exchange="amq.topic",
                         arg::queue="asdf",
                         arg::bindingKey="a.b.c");
    LocalQueue lq;
    Subscription sub = subMgr.subscribe(lq, "asdf");
    Message msg;
    #ifdef DEADLOCK
        msg = lq.get(5000000000000000000LL);
    #else
        int i=0;
        while(i < 5000000)
        {
            lq.get(msg);
            sleep(1);
            i++;
        }
    #endif
}



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:users-subscribe@qpid.apache.org


Re: Potential deadlock with LocalQueue::get() / Session::close()?

Posted by Gordon Sim <gs...@redhat.com>.
Rob Springer wrote:
> Hey all - I've noticed a problem when debugging some code, and it looks
> to my eyes like there's a potential deadlock situation using the timed
> LocalQueue::get() command when a fatal interrupt occurs.  I've posted
> what I hope is clear reproducer code below.  Could someone else take a
> quick look at it and tell me if I'm crazy or correct? 

The api is in general not safe to call from a signal handler. While the 
mutexes are re-entrant, deadlocks around condition variables is very likely.

If you need to use interrupts, maybe the best solution is to have a 
'signal queue' onto which notifications of signals are place, with a 
dedicated thread then processing that queue and invoking on the api to 
cleanup.

Of course that thread and the signal queue implementation will need to 
allow for the case where it is interrupted to actually handle the 
signal, but as that would be a more focused scope it would be easier 
than making the entire api interrupt safe.



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:users-subscribe@qpid.apache.org