Uploaded image for project: 'ActiveMQ Classic'
  1. ActiveMQ Classic
  2. AMQ-3567

The InactivityMonitor onException call interrupts itself when the readCheckTime was exceeded.

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Trivial
    • Resolution: Fixed
    • 5.5.0, 5.5.1
    • 5.6.0
    • JMS client
    • Patch Available

    Description

      The process that activemq uses to check if there has been inactivity for a connection has a flaw when it tries to close the connection because of inactivity. The current process generates the following interrupt exception.

       
      2011-10-25 12:13:56,878 | DEBUG | org.apache.activemq.util.ServiceSupport - Could not stop service: tcp://localhost/127.0.0.1:61616. Reason: java.lang.InterruptedException
      java.lang.InterruptedException
          at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1302)
          at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:253)
          at org.apache.activemq.transport.tcp.TcpTransport.doStop(TcpTransport.java:553)
          at org.apache.activemq.util.ServiceSupport.stop(ServiceSupport.java:70)
          at org.apache.activemq.transport.tcp.TcpTransport.stop(TcpTransport.java:570)
          at org.apache.activemq.transport.InactivityMonitor.stop(InactivityMonitor.java:132)
          at org.apache.activemq.transport.TransportFilter.stop(TransportFilter.java:65)
          at org.apache.activemq.transport.WireFormatNegotiator.stop(WireFormatNegotiator.java:91)
          at org.apache.activemq.util.ServiceSupport.dispose(ServiceSupport.java:43)
          at org.apache.activemq.transport.failover.FailoverTransport.disposeTransport(FailoverTransport.java:207)
          at org.apache.activemq.transport.failover.FailoverTransport.handleTransportFailure(FailoverTransport.java:223)
          at org.apache.activemq.transport.failover.FailoverTransport$3.onException(FailoverTransport.java:184)
          at org.apache.activemq.transport.TransportFilter.onException(TransportFilter.java:101)
          at org.apache.activemq.transport.WireFormatNegotiator.onException(WireFormatNegotiator.java:160)
          at org.apache.activemq.transport.InactivityMonitor.onException(InactivityMonitor.java:265)
          at org.apache.activemq.transport.InactivityMonitor$4.run(InactivityMonitor.java:185)
          at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
          at java.lang.Thread.run(Thread.java:680)
      

      This is caused because the spawned thread in the AbstractInactivityMonitor classes readCheck method calls the onException method. This method will then call the stopMonitorThreads method which subsequently calls the shutdownNow method of the ASYNC_TASKS executor. This call causes the executor to call the interrupt method for all active threads in the executor. The problem is that the calling thread is part of the ASYNC_TASKS executor and therefore it is generating the interrupt exception.

      Here is the stack trace of the call that is causing the interrupt.

       
      Daemon Thread [InactivityMonitor Async Task: java.util.concurrent.ThreadPoolExecutor$Worker@66da9ea4] (Suspended (entry into method interrupt in Thread))   
          Thread.interrupt() line: 902   
          ThreadPoolExecutor$Worker.interruptNow() line: 855   
          ThreadPoolExecutor.shutdownNow() line: 1167   
          InactivityMonitor.stopMonitorThreads() line: 363   
          InactivityMonitor.onException(IOException) line: 264   
          InactivityMonitor$4.run() line: 185   
          ThreadPoolExecutor$Worker.runTask(Runnable) line: 886   
          ThreadPoolExecutor$Worker.run() line: 908   
          Thread.run() line: 680  
      

      The solution is to replace the shutdownNow method call with shutdown. Subsequent testing with this change does not cause the interrupt exception.

      I was able to create a testcase that reproduces this issue. The testcase uses the useInactivityMonitor=false attribute to reproduce this issue, thanks Gary for the hint. Unfortunately there aren't any steps that I can use to determine that the raised interrupted exception was raised or not. The test will pass either way.

      A patch will be added to this issue.

      Attachments

        1. inactivitymonitor.patch
          8 kB
          Claudio Corsi

        Activity

          People

            Unassigned Unassigned
            ccorsi Claudio Corsi
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: