Hi,
I have a testcase that FTP outbound channel adapter will continuously upload files to FTP Server, and another FTP inbound channel adapter will download them accordingly. It's a circular upload&download.
but after running several hours, I found all of my thread are blocked and the circular testcase is hung without log output.
Below is the thread dump:
So I checked the source code in FTPClient._openDataConnection_ and I found this comment:Code:Name: XXX-6 State: RUNNABLE Total blocked: 1 Total waited: 196 Stack trace: java.net.PlainSocketImpl.socketAccept(Native Method) java.net.PlainSocketImpl.accept(PlainSocketImpl.java:390) - locked java.net.SocksSocketImpl@79d22a1b java.net.ServerSocket.implAccept(ServerSocket.java:453) java.net.ServerSocket.accept(ServerSocket.java:421) org.apache.commons.net.ftp.FTPClient._openDataConnection_(FTPClient.java:693) org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:551) org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:1704) org.springframework.integration.ftp.session.FtpSession.write(FtpSession.java:79) org.springframework.integration.file.remote.handler.FileTransferringMessageHandler.sendFileToRemoteDirectory(FileTransferringMessageHandler.java:222) org.springframework.integration.file.remote.handler.FileTransferringMessageHandler.handleMessageInternal(FileTransferringMessageHandler.java:136) org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73) org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:105) org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:96) org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:61) org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157) org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:128) org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288) org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149) org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendMessage(AbstractReplyProducingMessageHandler.java:175) org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendReplyMessage(AbstractReplyProducingMessageHandler.java:159) org.springframework.integration.handler.AbstractReplyProducingMessageHandler.produceReply(AbstractReplyProducingMessageHandler.java:124) org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleResult(AbstractReplyProducingMessageHandler.java:118) org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:100) org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73) org.springframework.integration.endpoint.PollingConsumer.doPoll(PollingConsumer.java:70) org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:146) org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:144) org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:207) org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:52) java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) java.lang.Thread.run(Thread.java:619)
I think the lack of network timeout setting is the cause of all my thread blocking indefinitely.// For now, let's just use the data timeout value for waiting for
// the data connection. It may be desirable to let this be a
// separately configurable value. In any case, we really want
// to allow preventing the accept from blocking indefinitely.
if (__dataTimeout >= 0)
server.setSoTimeout(__dataTimeout);
try {
socket = server.accept();
} finally {
server.close();
Although in official document(2.1.0.RELEASE), it mention to extend DefaultFtpSessionFactory and override two hook methods(postProcessClientAfterConnect and postProcessClientBeforeConnect), I think it's easy to ignore.
I think It's better to add network timeout setting as a necessary attribute to Ftp Session Factory, which are easy to cause thread blocking indefinitely.


Reply With Quote
