I believe that the attached patch solves this issue for both 0.8 and
0.10. If we stop the dispatcher thread before closing the session it
should not acquire a lock on _messageDeliveryLock. This may be useful to
apply it on M2.1.1.

Arnaud 

On Mon, 2008-03-03 at 08:15 -0500, Rafael Schloming wrote: 
> Aidan Skinner wrote:
> > On Fri, Feb 29, 2008 at 8:23 PM, Rafael Schloming <[EMAIL PROTECTED]> wrote:
> > 
> >> The deadlock is between the session's _messageDeliveryLock and the
> >>  Dispatcher's _lock. The dispatcher thread's main loop attempts to
> >>  acquire _lock first and then _messageDeliveryLock. The main thread
> >>  acquires _messageDeliveryLock first thing on close(...) and then
> >>  subsequently many levels down the stack attempts to acquire _lock in
> >>  order to call Dispatcher.rejectPending(...).
> > 
> > We found (and fixed) several similar problems on M2, it's probably
> > worth having a look at that code to make sure there aren't any cases
> > being missed.
> 
> I've just examined the M2.1 code, and I think the potential for the same 
> deadlock exists there:
> 
> AMQSession.close(long timeout) acquires _messageDeliveryLock and then 
> indirectly calls BasicMessageConsumer.close().
> 
> BasicMessageConsumer.close() calls syncWrite(BasicCancelOkBody.class). 
> This will block until AMQSession.confirmConsumerCancelled() completes in 
> another thread.
> 
> If the dispatcher thread happens to be holding _lock and waiting to 
> acquire _messageDeliveryLock, the confirmConsumerCancelled() in the 
> other thread will never be able to acquire _lock and the same deadlock 
> should occur.
> 
> --Rafael
> 
Index: org/apache/qpid/client/AMQSession.java
===================================================================
--- org/apache/qpid/client/AMQSession.java	(revision 632970)
+++ org/apache/qpid/client/AMQSession.java	(working copy)
@@ -459,6 +459,10 @@
                         // + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 6));
         }
 
+        if( _dispatcher != null )
+        {
+            _dispatcher.setConnectionStopped(true);
+        }
         synchronized (_messageDeliveryLock)
         {
 

Reply via email to