You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Jens Viebig <jv...@como.com> on 2005/09/01 18:02:29 UTC

VFS FTPClientWrapper Broken pipe

Hello List,
i'm using VFS to regulary check some files on an FTP server. This works fine for a long time, but after a while the check crashes with the following stacktrace:

org.apache.commons.vfs.FileSystemException: Could not determine the type of file ftp://user:password@myserver.com/myfile.txt.
        at org.apache.commons.vfs.provider.AbstractFileObject.attach()V(Optimized Method)
        at org.apache.commons.vfs.provider.AbstractFileObject.exists()Z(AbstractFileObject.java:391)
        at my.class.Something.toDo(Unknown Source)
        at java.lang.Thread.run()V(Unknown Source)
        at java.lang.Thread.startThreadFromVM(Ljava.lang.Thread;)V(Unknown Source)
Caused by: java.net.SocketException: Broken pipe
        at jrockit.net.SocketNativeIO.write(IIIZ)I(Unknown Source)
        at jrockit.net.SocketNativeIO.write(III)I(Unknown Source)
        at jrockit.io.NativeIO.write(Ljava.io.FileDescriptor;II)I(Optimized Method)
        at java.net.AbstractSocketImpl$2.write(II)V(Optimized Method)
        at jrockit.io.NativeIOOutputStream.write([BII)V(Optimized Method)
        at java.io.BufferedOutputStream.flushBuffer()V(Optimized Method)
        at java.io.BufferedOutputStream.write(I)V(Optimized Method)
        at org.apache.commons.net.telnet.Telnet._sendByte(I)V(Optimized Method)
        at org.apache.commons.net.telnet.TelnetOutputStream.write(I)V(Optimized Method)
        at org.apache.commons.net.io.ToNetASCIIOutputStream.write([BII)V(Optimized Method)
        at sun.nio.cs.StreamEncoder$CharsetSE.writeBytes()V(StreamEncoder.java:325)
        at sun.nio.cs.StreamEncoder$CharsetSE.implWrite([CII)V(Optimized Method)
        at sun.nio.cs.StreamEncoder.write([CII)V(StreamEncoder.java:136)
        at java.io.OutputStreamWriter.write([CII)V(OutputStreamWriter.java:191)
        at java.io.BufferedWriter.flushBuffer()V(BufferedWriter.java:107)
        at java.io.BufferedWriter.flush()V(BufferedWriter.java:228)
        at org.apache.commons.net.ftp.FTP.sendCommand(Ljava.lang.String;Ljava.lang.String;)I(Optimized Method)
        at org.apache.commons.net.ftp.FTP.sendCommand(ILjava.lang.String;)I(Optimized Method)
        at org.apache.commons.net.ftp.FTP.port(Ljava.net.InetAddress;I)I(Optimized Method)
        at org.apache.commons.vfs.provider.ftp.FTPClientWrapper.listFiles(Ljava.lang.String;Ljava.lang.String;)[Lorg.apache.commons.net.ftp.FTPFile;(Optimized Method)
        at org.apache.commons.vfs.provider.ftp.FtpFileObject.doGetChildren()V(Optimized Method)
        at org.apache.commons.vfs.provider.ftp.FtpFileObject.getChildFile(Ljava.lang.String;Z)Lorg.apache.commons.net.ftp.FTPFile;(Optimized Method)
        at org.apache.commons.vfs.provider.ftp.FtpFileObject.getInfo(Z)V(Optimized Method)
        at org.apache.commons.vfs.provider.ftp.FtpFileObject.doAttach()V(Optimized Method)
        ... 6 more

When it comes to that error, the filesystem provider never recovers from that crash and all actions on files on the same ftp server fail. The ftp server works fine, i can connect fine from the commandline. it seems that the VFS ftp provider tries to reuse that old damaged connection, i don't see a new attempt to login in my ftp server log. There is no connection from VFS to the ftp server.

I looked in the source code of FTPClientWrapper, and tracked the error down to the listFiles function:

...
    public FTPFile[] listFiles(String key, String relPath) throws IOException
    {
        try
        {
            return getFtpClient().listFiles(key, relPath);
        }
        catch (FTPConnectionClosedException e)
        {
            disconnect();
            return getFtpClient().listFiles(key, relPath);
        }
    }
...

the FTPClient of commons.net throws FTPConnectionClosedException and IOException. if a FTPConnectionClosedException is thrown everything is fine, the old connection is closed and a new one is created. If a more general IOException is thrown the connection is not closed and not set to null, so the FTPClientWrapper tries to use it again. Normally isConnected() should fail then, but it seems that it still returns true und is a weak test. I suggest that the connection should also be disconnected and set to null on more general errors, if there is an IOException there is a big chance that the connection is not usable anymore.

Maybe like this:

    public FTPFile[] listFiles(String key, String relPath) throws IOException
    {
        try
        {
            return getFtpClient().listFiles(key, relPath);
        }
        catch (FTPConnectionClosedException e)
        {
            disconnect();
            return getFtpClient().listFiles(key, relPath);
        }
        catch (IOException ie)
        {
            disconnect();
            throw ie;
        }
    }

This fix should be applied to all functions in FTPClientWrapper

Maybe you have a better approach on fixing this issue ?