Hang on socket close after connection reset or connection timed out

H

Helene Unterwieser

Hi all,

i have a rather nasty problem here and the situation is pretty critical
so please help wit anything that comes to your mind.
There is a thread with a server socket which accepts a connection and
spawns another thread with the created client socket. The connection
works for some time without problems. Then a IOException is thrown when
writing to the client socket, either "Connection reset" or "Connection
timed out". To handle the broken connection, the client socket should
then be closed by the thread but hangs in the close method forever.
So the question is how can a "Connection reset" or "Connection timed
out" be reproduced when sending data? If this is possible maybe the hang
on close can be reproduced.
 
B

bencoe

Hi all,

i have a rather nasty problem here and the situation is pretty critical
so please help wit anything that comes to your mind.
There is a thread with a server socket which accepts a connection and
spawns another thread with the created client socket. The connection
works for some time without problems. Then a IOException is thrown when
writing to the client socket, either "Connection reset" or "Connection
timed out". To handle the broken connection, the client socket should
then be closed by the thread but hangs in the close method forever.
So the question is how can a "Connection reset" or "Connection timed
out" be reproduced when sending data? If this is possible maybe the hang
on close can be reproduced.

Sounds like you're hitting a blocking situation with the client
socket... One way around this is using the method.

Socket.setSoTimeout(int timeout)

This sets a maximum wait time on a socket before an exception is
automatically thrown, this can be used in situations such as the one
you're describing to make sure that you don't block on a socket
indefinitely.
 
E

Esmond Pitt

Sounds like you're hitting a blocking situation with the client
socket...

No it doesn't.
One way around this is using the method.
Socket.setSoTimeout(int timeout)

This sets a maximum wait time on a socket before an exception is
automatically thrown, this can be used in situations such as the one
you're describing to make sure that you don't block on a socket
indefinitely.

That only applies to read operations, not to write or close operations.
It has no relevance to the question.

'Connection reset' happens when you write data to a connection when the
other end is already closed.

You can't get 'connection timed out' from a socket accepted by a server.
It is impossible. You also can't get it when either reading or writing
in the client. You can only get it *in the client* when constructing or
connecting the socket.

A close of a socket can only block if:

(a) you are closing the output stream, it is buffered, it hasn't been
flushed, the client is behind with its reads so its socket receive
buffer is full, and your socket send buffer is full; *or*

(b) you have set a large positive linger timeout - don't mess with this
setting, *or*

(c) You are closing from another thread and you encounter Java
synchronization.
 
K

Knute Johnson

Esmond said:
'Connection reset' happens when you write data to a connection when the
other end is already closed.

Or if the reading end is blocked and the writing end is closed.
 
B

bencoe

No it doesn't.

Based on the limited information provided by Helene, I think there is
a good chance that the client is blocking on a read operation. Perhaps
you could clarify a bit Helene, or post the chunk of code that appears
to not be exiting? This would be better than arguing, without complete
information.

Ben.
 
E

Esmond Pitt

Based on the limited information provided by Helene, I think there is
a good chance that the client is blocking on a read operation.

I'm sorry but this doesn't make sense. If the client was blocking on a
read operation, (a) the connection would still be open, so there is no
reason for 'connection reset', and (b) the flush and close by the sender
would be able to write and complete and not block.
 
E

Esmond Pitt

Knute said:
Or if the reading end is blocked and the writing end is closed.

'Connection reset' is only encountered by the writing end. If the
writing end was closed it would get 'socket closed'.
 
K

Knute Johnson

Esmond said:
'Connection reset' is only encountered by the writing end. If the
writing end was closed it would get 'socket closed'.

I hate to be disagreeable but that is not what I am getting. On the app
I am currently working on, if the reading end is blocked on read and the
writing end is closed, I get a connection reset.

C:\com\knutejohnson\tsn>java -jar Client.jar
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io_ObjectInputStream$PeekInputStream.peek(Unknown Source)
at java.io_ObjectInputStream$BlockDataInputStream.peek(Unknown
Source)
at
java.io_ObjectInputStream$BlockDataInputStream.peekByte(Unknown Sourc
e)
at java.io_ObjectInputStream.readObject0(Unknown Source)
at java.io_ObjectInputStream.readObject(Unknown Source)
at com.knutejohnson.tsn.Client.run(Client.java:73)
at java.lang.Thread.run(Unknown Source)
 
E

Esmond Pitt

Knute said:
... that is not what I am getting. On the app
I am currently working on, if the reading end is blocked on read and the
writing end is closed, I get a connection reset.

That can only be because you have also done a write from this end that
got the reset reply because the other end was closed. There's no wire
protocol associated with a TCP read operation, so there is no way it can
provoke a reset.
 
K

Knute Johnson

Esmond said:
That can only be because you have also done a write from this end that
got the reset reply because the other end was closed. There's no wire
protocol associated with a TCP read operation, so there is no way it can
provoke a reset.

You want to see the code, there isn't a write in it?
 
E

Esmond Pitt

Knute said:
You want to see the code, there isn't a write in it?

Sure, if you like. Send it to me privately via
http://www.telekinesis.com.au/wipv3_6/people.A21. There are other
explanations for ECONNRESET but they usually emanate from the other end
and they don't have anything to do with read blocks. Does the writing
end fiddle with SO_LINGER? or is it MS IIS by any chance (which does)?

There's also the local condition 'software caused connection abort',
WSAECONNABORTED (10053), but that's not what's happenin here. For more
info on that see
http://forum.java.sun.com/thread.jspa?forumID=11&threadID=748677.
 
K

Knute Johnson

Esmond said:
Sure, if you like. Send it to me privately via
http://www.telekinesis.com.au/wipv3_6/people.A21. There are other
explanations for ECONNRESET but they usually emanate from the other end
and they don't have anything to do with read blocks. Does the writing
end fiddle with SO_LINGER? or is it MS IIS by any chance (which does)?

There's also the local condition 'software caused connection abort',
WSAECONNABORTED (10053), but that's not what's happenin here. For more
info on that see
http://forum.java.sun.com/thread.jspa?forumID=11&threadID=748677.

Here is a really simple example. Run s then c. If you don't get a
java.net.SocketExcepion: Connection reset I'll eat my hat (or a
reasonable facsimile like a cheeseburger). I'm not being rude but I
won't be able to reply for a week to 10 days. Sorry.

import java.io.*;
import java.net.*;

public class s {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(1111);
Socket s = ss.accept();
Thread.sleep(1000);
}
}

import java.io.*;
import java.net.*;

public class c {
public static void main(String[] args) {
try {
Socket s = new Socket("127.0.0.1",1111);
System.out.println(
"connected to: " + s.getInetAddress().getHostAddress());
InputStream is = s.getInputStream();
is.read();
} catch (Exception e) {
System.out.println(e);
}
}
}
 
E

Esmond Pitt

Knute said:
Here is a really simple example. Run s then c. If you don't get a
java.net.SocketExcepion: Connection reset I'll eat my hat (or a
reasonable facsimile like a cheeseburger).

My apologies, you are correct and I have forgotten this for the Nth time
this year, so I will eat the hat (hold the cheeesburger). Exiting a JVM
or indeed any Unix or Windows process causes a TCP RST to be issued on
all sockets that are still open. Somewhat counter-intuitive behaviour
IMO, you would expect the OS to close the fd and therefore TCP to issue
a FIN. Obviously TCP gets in first somehow.

I don't know that that has any bearing on the OP's problem though?
 
G

Gordon Beaton

Exiting a JVM or indeed any Unix or Windows process causes a TCP RST
to be issued on all sockets that are still open. Somewhat
counter-intuitive behaviour IMO, you would expect the OS to close
the fd and therefore TCP to issue a FIN.

On "not Unix" Linux (Fedora 6) using JDK 1.6, in.read() returned -1
(EOF) and no exception was raised when I tested the posted example. I
see with Wireshark that FIN was sent, not RST. Got the same results on
Solaris 8.

Maybe its just a Windows thing?

/gordon

--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top