Hi,
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
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.Code:int len = this.socketChannel.read(this.rawBuffer);
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
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.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); }
Hopefully my analysis is accurate and you will be able to work on a fix for this?
Regards
Ted


Reply With Quote
