In other words you are still guessing. I am *not* guessing, and all the
references cited above agree with me.
I'm not guessing anymore. I proved it to myself a while back, another
poster also acknowledged that shutdown calls work, and now I took a
saturday morning off to prove my point. You fail to acknowledge that
the shutdown() calls can work and demonstratably Channel.close()
sometimes does not. I believe the shutdown() calls are clearer -
certainly from a JavaDoc standpoint that is true. Regardless, here's
the proof.
The code below is taken from the bug report link above - I only changed
the package and one print statement after my code in the finally block.
My system is Suse Pro 9.2 Linux, using the default jvm
/usr/lib/jvm/java-1.4.2-sun-1.4.2.05 . The default smtp server is
postfix, which by default only accepts connections from localhost.
Conclusions:
- Channel.close() does not work aa the bug report stated
- shutdownOutput() works just fine ;-) , ie via 'netstat -an | grep
CLOSE_WAIT'
- without socket.close() , isConnected() return true always, with
socket.close() about half the time the code returns false, but as
Gordon eloquently once said:
- isConnected() and isInputShutdown() cannot be relied upon to say
anything meaningful about the state of the actual connection.
I put some simple System.currentTimeMillis() in to profile - care to
take the pepsi challege with selectNow() ?
Let me know about the pills, they are now working for me.
Best
EJP
Don't bogart - I mean it is good stuff man ;-).
Best likewise,
iksrazal
package com.whitezone;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.SocketChannel;
import java.util.StringTokenizer;
// Test case code for file descriptor leak.
// The following should produce somewhere near 150 sockets in
CLOSE_WAIT state.
//
// The problem appears to be in
sun.nio.ch.SocketAdapter.SocketInputStream.read(ByteBuffer);
//
public class TestClose implements Runnable {
public static final String SMTP_HOSTNAME = "localhost";
public void run()
{
InetSocketAddress sockAddr = new
InetSocketAddress(SMTP_HOSTNAME, 25);
SocketChannel sChannel = null;
Socket socket = null;
try
{
sChannel = SocketChannel.open();
sChannel.connect(sockAddr);
// I've noticed that if I remove this line the problem no
longer happens
sChannel.socket().setSoTimeout(5000);
socket = sChannel.socket();
BufferedReader lineRdr = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String result = null;
do
{
// before performing the first readline the channel is
unregistered
System.err.println("before first readline: isOpen =
"+sChannel.isOpen()+" isRegistered="+sChannel.isRegistered());
result = lineRdr.readLine();
System.err.println("<- "+result);
// after performing it is registered.
System.err.println("after first readline: isOpen =
"+sChannel.isOpen()+" isRegistered="+sChannel.isRegistered());
} while(result != null && result.length() > 0 &&
result.matches("^[1-5][0-9]{2}-"));
if(result == null || result.length() == 0)
{
System.err.println("Received truncated response from SMTP server "
+ sockAddr.getHostName());
return;
}
// Tokenize the last line result
//
StringTokenizer t = new StringTokenizer(result);
int rc = Integer.parseInt(t.nextToken());
if(rc != 220) return;
//
// Send the QUIT command causing the server side to close its end of
the connection
//
String cmd = "QUIT\r\n";
socket.getOutputStream().write(cmd.getBytes());
System.err.println("-> "+cmd);
do
{
result = lineRdr.readLine();
System.err.println("<- "+result);
} while(result != null && result.length() > 0 &&
result.matches("^[1-5][0-9]{2}-"));
if(result == null || result.length() == 0)
{
System.err.println("Received truncated response from SMTP server "
+ sockAddr.getHostName());
return;
}
}
catch (Exception e) {
e.printStackTrace();
}
finally
{
try {
System.err.println("before close: isOpen =
"+sChannel.isOpen()+" isRegistered="+sChannel.isRegistered());
System.err.println("Closing SMTP socket channel
"+sChannel);
System.err.println("channel.socket().isConnected = "+
sChannel.socket().isConnected());
if (sChannel != null) {
//sChannel.close();
long start = System.currentTimeMillis();
System.currentTimeMillis();
Socket socket_close = sChannel.socket();
// by socket_close.shutdownOutput() itself,
CLOSE_WAIT issue fixed
socket_close.shutdownOutput();
// with socket_close.close() , isConnected
returns false sometimes
socket_close.close();
long end = System.currentTimeMillis();
System.err.println("Closed SMTP socket channel
"+sChannel+", Execution time was "+(end-start)+" ms.");
// The socket is still connected here.
System.err.println("\n\nAFTER shutdownOutput
channel.socket().isConnected = "+sChannel.socket().isConnected());
}
}
catch (Exception e) {
System.err.println("Exception on close:");
e.printStackTrace();
}
}
return;
}
public static void main(String[] args) {
TestClose test = new TestClose();
for(int i = 0; i < 150; i++) {
// this bug seems only to appear if different threads are
reading the channels
Thread thread = new Thread(test);
thread.start();
try {thread.join(); } catch(InterruptedException e) { }
}
System.err.println("Going to sleep.... run netstat -an | grep
CLOSE_WAIT ");
while(true) {
try { Thread.sleep(10000); } catch(InterruptedException e) {}
}
}
}