Discussion:
org.apache.commons.net.ftp.FTPClient: disconnect() hangs
Ito Kazumitsu
2004-10-10 22:29:03 UTC
Permalink
Hi,

My next target application to be run with Kaffe is openadaptor
(http://www.openadaptor.org/).

While testing openadaptor, I found a case where the package
org.apache.commons.net.ftp from Jakarta Commons http://jakarta.apache.org/
does not work properly.

The attached program, which ends normally with Sun's JDK,
will not stop with kaffe. Does it go into a deadlock?

bash-2.05b$ cat TestApacheFTP.java
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
public class TestApacheFTP
{
private FTPClient _ftpClient;
public static void main(String[] args) throws Exception
{
TestApacheFTP ftp = new TestApacheFTP();
ftp.connect(args[0], 21);
ftp.login(args[1], args[2]);
ftp.close();
}
public void connect(String hostName, int port) throws Exception
{
debug("Connecting to " + hostName + " on port " + port);
_ftpClient = new FTPClient();
_ftpClient.connect(hostName, port);
if (!FTPReply.isPositiveCompletion(_ftpClient.getReplyCode()))
{
_ftpClient.disconnect();
throw new Exception("Failed to connect");
}
debug("ApacheFTP object initialised and connected to " + hostName);
}
public void login(String userName, String password) throws Exception
{
debug("Logging in " + userName);
if (!_ftpClient.login(userName, password))
{
_ftpClient.disconnect();
throw new Exception(userName + " Failed to login");
}
debug(userName + " logged in");
}
public void close() throws Exception
{
debug("trying to close FTP Connection");
if (_ftpClient.isConnected())
{
debug("disconnecting FTP Connection");
_ftpClient.disconnect();
debug("FTP Connection closed");
}
}
private static void debug(String s)
{
System.err.println("DEBUG: " + s);
System.err.flush();
}
}
bash-2.05b$ kaffe TestApacheFTP localhost kaz ilvmke413
DEBUG: Connecting to localhost on port 21
DEBUG: ApacheFTP object initialised and connected to localhost
DEBUG: Logging in kaz
DEBUG: kaz logged in
DEBUG: trying to close FTP Connection
DEBUG: disconnecting FTP Connection
^C
Ito Kazumitsu
2004-10-11 08:44:00 UTC
Permalink
In message "[kaffe] org.apache.commons.net.ftp.FTPClient: disconnect() hangs"
Post by Ito Kazumitsu
While testing openadaptor, I found a case where the package
org.apache.commons.net.ftp from Jakarta Commons http://jakarta.apache.org/
does not work properly.
The attached program, which ends normally with Sun's JDK,
will not stop with kaffe. Does it go into a deadlock?
Whether or not this problem occurs depends mainly on
whether the system property line.separator is equal to
"\r\n".

If line.separator is "\r\n", it is OK, which is the case
I had with Sun's JDK on Windows. If line.separator is not
"\r\n", the problem may occur, which is the case I had with
Kaffe on Linux. Setting line.separator to "\r\n", I got
a good result on Linux, too.

But even if the line.separator is set to "\n", Sun's JDK
on Windows gives a good result.

And here is the cause of the problem on kaffe.

When disconnect() on a FTP client is called, close() on its
org.apache.commons.net.io.FromNetASCIIInputStream is called.
FromNetASCIIInputStream is a subclass of java.io.PushbackInputStream
and close() is inherited. PushbackInputStream's close() is
synchronized, so close() tries to lock the input stream object.

Unfortunately, another thread is still reading from the input
stream. PushbackInputStream's read() is also synchronized.
So close() cannot get a lock until the read() ends. The reading
thread seems to be waiting for some data from the FTP server,
which will never come. So both read() and close() will never
finish.

If Kaffe's (that is GNU Classpath's) java.io.PushbackInputStream
is correct, this problem may be directed to Jakarta Commons.
But the misterious thing is that Sun's JDK does not show the
problem. If Kaffe's java.io.PushbackInputStream is correct,
Sun's JDK may be neglecting some necessary synchronization
or uses some magic to avoid the problematic situation.
Ito Kazumitsu
2004-10-11 16:08:48 UTC
Permalink
I> Unfortunately, another thread is still reading from the input
I> stream. PushbackInputStream's read() is also synchronized.
I> So close() cannot get a lock until the read() ends. The reading
I> thread seems to be waiting for some data from the FTP server,
I> which will never come. So both read() and close() will never
I> finish.

I have found a workaround for this. Calling logout() before calling
disconnect() will help.

Loading...