ActiveMQ
  1. ActiveMQ
  2. AMQ-1438

When in XA Transaction Active-MQ integrated with OpenEJB hangs in the isSameRM method of LocalAndXATransaction.

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 4.1.1
    • Fix Version/s: 4.1.2
    • Component/s: Connector, Transport
    • Labels:
      None
    • Environment:

      All

      Description

      I was facing a problem with the AMQ 4.1 with the LocalAndXATransaction class's isSameRM waiting indefinitely. The wait is because waitForBrokerInfo calls brokerInfoReceived.await()
      where brokerInfoReceived is a countdown latch. Once this is waiting it
      never gets resumed.

      To trigger it the method onCommand(final Object o) has to be called on
      org.apache.activemq.ActiveMQConnection.

      1. AMQ-1438.patch
        2 kB
        Manu T George

        Activity

        Manu T George created issue -
        Hide
        Manu T George added a comment -
        Show
        Manu T George added a comment - https://issues.apache.org/jira/browse/OPENEJB-702 is blocked because of this
        Hide
        Manu T George added a comment -
        Show
        Manu T George added a comment - https://issues.apache.org/jira/browse/GERONIMO-3354 is depending on this
        Hide
        Manu T George added a comment -

        This fixes the issue. Running the tests shows the same no of failures as before applying the patch so assuming it doesn't break anything.

        Show
        Manu T George added a comment - This fixes the issue. Running the tests shows the same no of failures as before applying the patch so assuming it doesn't break anything.
        Manu T George made changes -
        Field Original Value New Value
        Attachment AMQ-1438.patch [ 15805 ]
        Hide
        Manu T George added a comment -

        I believe I owe an explanation for the JIRA.

        The problem faced is a hang in the method below when the Geronimo TM calls it.

        public boolean isSameRM(XAResource other) throws XAException {
        if (other instanceof WrapperNamedXAResource)

        { return xaResource.isSameRM(((WrapperNamedXAResource)other).xaResource); }

        return false;
        }

        The hang is because this method invokes org,apache.activemq.ActiveMQConnection.getResourceManagerId()

        This method is shown below

        public String getResourceManagerId() throws JMSException

        { waitForBrokerInfo(); if( brokerInfo==null ) throw new JMSException("Connection failed before Broker info was received."); return brokerInfo.getBrokerId().getValue(); }

        The waitForBrokerInfo() method is shown below

        private void waitForBrokerInfo() throws JMSException {
        try

        { brokerInfoReceived.await(); }

        catch (InterruptedException e)

        { Thread.currentThread().interrupt(); throw JMSExceptionSupport.create(e); }

        }

        Once await is called on brokerInfoReceived which is a countdown latch currently brokerInfoReceived.countDown() never gets called. Actually this should get called on the
        else if ( command.isBrokerInfo() )

        { this.brokerInfo = (BrokerInfo)command; brokerInfoReceived.countDown(); this.optimizeAcknowledge &= !this.brokerInfo.isFaultTolerantConfiguration(); }

        block of the onCommand method of org.apache.activemq.ActiveMQConnection.

        This is not getting called.

        On investigating and with some help from AMQ IRC , I found that there are two methods in org.apache.activemq.transport.vm.VMTransport. They are given below

        protected void syncOneWay(Object command){
        final TransportListener tl=peer.transportListener;
        prePeerSetQueue=peer.prePeerSetQueue;
        if(tl==null)

        { prePeerSetQueue.add(command); }

        else

        { tl.onCommand(command); }

        }

        protected void asyncOneWay(Object command) throws IOException{
        messageQueue=getMessageQueue();
        try

        { messageQueue.put(command); wakeup(); }

        catch(final InterruptedException e)

        { log.error("messageQueue interupted",e); throw new IOException(e.getMessage()); }

        }

        The problem here is even when i set async=true for the VMTransport when the command BrokerInfo is sent syncOneWay is called. At that time TransportListener tl=null. So it gets added to prePeerSetQueue. The reason for this happening is that in org.apache.activemq.transport.vm.VMTransportFactory when the below lines are called a brokerInfo is sent as server.connect() is called. The async=true is not yet set resulting in the syncOneWay getting called. Only after that IntrospectionSupport.setProperties(vmtransport,options); is called and async is set to true. Due to this inconsistency the BrokerInfo command gets lost.

        VMTransport vmtransport=server.connect();
        IntrospectionSupport.setProperties(vmtransport,options);

        I hope I made the issue clear. Can someone verify the patch or make a fix for this.

        Show
        Manu T George added a comment - I believe I owe an explanation for the JIRA. The problem faced is a hang in the method below when the Geronimo TM calls it. public boolean isSameRM(XAResource other) throws XAException { if (other instanceof WrapperNamedXAResource) { return xaResource.isSameRM(((WrapperNamedXAResource)other).xaResource); } return false; } The hang is because this method invokes org,apache.activemq.ActiveMQConnection.getResourceManagerId() This method is shown below public String getResourceManagerId() throws JMSException { waitForBrokerInfo(); if( brokerInfo==null ) throw new JMSException("Connection failed before Broker info was received."); return brokerInfo.getBrokerId().getValue(); } The waitForBrokerInfo() method is shown below private void waitForBrokerInfo() throws JMSException { try { brokerInfoReceived.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw JMSExceptionSupport.create(e); } } Once await is called on brokerInfoReceived which is a countdown latch currently brokerInfoReceived.countDown() never gets called. Actually this should get called on the else if ( command.isBrokerInfo() ) { this.brokerInfo = (BrokerInfo)command; brokerInfoReceived.countDown(); this.optimizeAcknowledge &= !this.brokerInfo.isFaultTolerantConfiguration(); } block of the onCommand method of org.apache.activemq.ActiveMQConnection. This is not getting called. On investigating and with some help from AMQ IRC , I found that there are two methods in org.apache.activemq.transport.vm.VMTransport. They are given below protected void syncOneWay(Object command){ final TransportListener tl=peer.transportListener; prePeerSetQueue=peer.prePeerSetQueue; if(tl==null) { prePeerSetQueue.add(command); } else { tl.onCommand(command); } } protected void asyncOneWay(Object command) throws IOException{ messageQueue=getMessageQueue(); try { messageQueue.put(command); wakeup(); } catch(final InterruptedException e) { log.error("messageQueue interupted",e); throw new IOException(e.getMessage()); } } The problem here is even when i set async=true for the VMTransport when the command BrokerInfo is sent syncOneWay is called. At that time TransportListener tl=null. So it gets added to prePeerSetQueue. The reason for this happening is that in org.apache.activemq.transport.vm.VMTransportFactory when the below lines are called a brokerInfo is sent as server.connect() is called. The async=true is not yet set resulting in the syncOneWay getting called. Only after that IntrospectionSupport.setProperties(vmtransport,options); is called and async is set to true. Due to this inconsistency the BrokerInfo command gets lost. VMTransport vmtransport=server.connect(); IntrospectionSupport.setProperties(vmtransport,options); I hope I made the issue clear. Can someone verify the patch or make a fix for this.
        David Jencks made changes -
        Assignee David Jencks [ djencks ]
        David Jencks committed 640340 (2 files)
        Reviews: none

        AMQ-1438 Force the vm transport to finish configuring itself when its constructed so brokerInfo is immediately available so XAResource.isSameRM() can work properly. Modified patch to make it more thread-safe. Original patch from Manu T George

        Hide
        David Jencks added a comment -

        Applied modified version of the patch in rev 640340. Passed options into server.connect method so that correct TransportAcceptListener is sure to be used.

        Show
        David Jencks added a comment - Applied modified version of the patch in rev 640340. Passed options into server.connect method so that correct TransportAcceptListener is sure to be used.
        Hide
        David Jencks added a comment -

        Would be a good idea to check if it works in 5.1

        Show
        David Jencks added a comment - Would be a good idea to check if it works in 5.1
        David Jencks made changes -
        Status Open [ 1 ] Closed [ 6 ]
        Resolution Fixed [ 1 ]
        Hiram Chirino committed 647882 (1 file)
        Reviews: none

        Added test case to trunk showing that AMQ-1438 is no longer an issue on the trunk.

        Jeff Turner made changes -
        Project Import Fri Nov 26 22:32:02 EST 2010 [ 1290828722158 ]

          People

          • Assignee:
            David Jencks
            Reporter:
            Manu T George
          • Votes:
            2 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development