Uploaded image for project: 'Spring Integration'
  1. Spring Integration
  2. INT-1937

Infinite loop in TcpNioConnection caused by TCP client abnormal exit

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Complete
    • Affects Version/s: 2.0.4
    • Fix Version/s: 2.0.5
    • Component/s: TCP/UDP Support
    • Environment:
      I get the same problem with either a Windows server or OSX

      Description

      I've created a system whereby I have both a TCP inbound adapter and a corresponding TCP outbound adapter with the connection factory working in server mode and NIO is true. I also configured the connection factory to use a task executor.

      When a message arrives on a socket I can see that the doRead method of TcpNioConnection is called and I can further see that in this method the private variable writingToPipe is set to true. Once the code has got past checkForAssmebler you can see that another thread is started which executes the run method of the TcpNioConnection.

      The problem is that if after the checkForAssembler method executes the TCP client dies then the the following code (still within doRead) throws an exception

      Code:

      int len = this.socketChannel.read(this.rawBuffer);

      Now remember that the variable writingToPipe is still set to true at this point. The problem then is that the run method of the other thread is waiting for writingToPipe to become false (see method dataAvailable called from the run method). Since the run method is called from a loop of the ThreadPoolExecutor that loop never ends.

      In fact the situation gets worse because each time the run method executes another thread is spawned and does exactly the same. Because writingToPipe is true each time the run method of TcpNioConnection is executed it determines that there is more data in the pipe (which there isn't) and creates a new assembler just as the comment says

      Code:

      if (dataAvailable())

      { // there is more data in the pipe; run another assembler // to assemble the next message, while we send ours this.executionControl.incrementAndGet(); this.taskExecutor.execute(this); }

      Eventually all your task executor threads are used up and no other clients can connect. In fact if you have a large enough pool of threads then you will see your CPU usage max out as all the threads are in an infinite loop.

      Log file attched

        Attachments

          Activity

            People

            • Assignee:
              grussell Gary Russell
              Reporter:
              tedp Ted Pritchard
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: