Weird Socket OutOfMemoryException on read from broken connection

M

MG

Hi
I'm testing some client/server style socket code and running into a
strange situation... Client estblishes a socket to the server (also in
java), sends ands receives messages and all is well. Then I kill the
server program. When the client tries to send to server through the
existing socket I see a few interesting things, including one issue
that feels like a bug in java:
1. The client can write() and flush() to the socket's OutputStream
without errors. Seems weird to me since the other end of the socket is
dead.
2. The client then tries to read() a single byte of the (expected)
reply from the socket's InputStream. This is the where the Bug kicks
in... instead of getting a SocketException the CPU goes to 100%, the
vm memory usage climbs like crazy, and the an OutOfMemoryException is
thrown. This is a terrible way to handle an expected error condition.

But wait, there's more...

3. In the course of debugging this I added a bunch of
System.out.println() statements. When I did this the behavior changed
so that the read() would immediately throw a SocketException without
undue CPU or memory usage. Remove the println()'s from the code and it
goes back the 100% CPU and OutOfMemory issues.

I'm using java 1.3.1-b24 but also tried 1.4 with no change. OS is
Win2k.

Any insight would be appreciated!

Thanks
Mark
 
R

Robert Olofsson

MG ([email protected]) wrote:
: 1. The client can write() and flush() to the socket's OutputStream
: without errors. Seems weird to me since the other end of the socket is
: dead.

Nah, not that strange. Your network subsystem will most probably
gather a block (1500 bytes or something like that) before it sends
data. A flush may cause the data to be sent, but do you call flush
more than once?
Before you have sent the data and/or have tried to read you will not
know if the connection is down.

: 2. The client then tries to read() a single byte of the (expected)
: reply from the socket's InputStream. This is the where the Bug kicks
: in... instead of getting a SocketException the CPU goes to 100%, the
: vm memory usage climbs like crazy, and the an OutOfMemoryException is
: thrown. This is a terrible way to handle an expected error condition.

I have not seen this unless I have done something stupid. Can you
show some code?

How many bytes do you read? It may be that you loop in a read that
reads zero (0) bytes.

/robo
 
M

MG

Comments below...

MG ([email protected]) wrote:
: 1. The client can write() and flush() to the socket's OutputStream
: without errors. Seems weird to me since the other end of the socket is
: dead.

Nah, not that strange. Your network subsystem will most probably
gather a block (1500 bytes or something like that) before it sends
data. A flush may cause the data to be sent, but do you call flush
more than once?
Before you have sent the data and/or have tried to read you will not
know if the connection is down.

I call flush once after issuing two write()s. Would calling it more
than once make a difference? I can't seem to find any lower level
methods to see if anything actually happened. The Socket class doesn't
expose much and SocketInputStream and SocketOutputStream are not
public classes...
: 2. The client then tries to read() a single byte of the (expected)
: reply from the socket's InputStream. This is the where the Bug kicks
: in... instead of getting a SocketException the CPU goes to 100%, the
: vm memory usage climbs like crazy, and the an OutOfMemoryException is
: thrown. This is a terrible way to handle an expected error condition.

I have not seen this unless I have done something stupid. Can you
show some code?

How many bytes do you read? It may be that you loop in a read that
reads zero (0) bytes.

/robo

The relavent code for reading the first byte is just:
int r = inputStream.read();

This is in a while() loop but it never returns from the first call.

I normally use a BufferedInputStream wrapped around the
socket.getInputStream(), but I've also tried it without the
BufferedInputStream and it does the same thing.

Thanks
Mark
 
S

Steve Horsley

Comments below...

(e-mail address removed) (Robert Olofsson) wrote in message


I call flush once after issuing two write()s. Would calling it more than
once make a difference? I can't seem to find any lower level methods to
see if anything actually happened. The Socket class doesn't expose much
and SocketInputStream and SocketOutputStream are not public classes...

Multiple flush()s probably won't make a difference. If the remote end
offered a 32K window, you can send up to 32K before even beginning to fill
the local buffers. However, having sent something you will now be
operating on retransmit timers, and will _eventually_ discover the broken
connection.
The relavent code for reading the first byte is just:
int r = inputStream.read();

This is in a while() loop but it never returns from the first call.

And if read() keeps on immediately returning -1? Read the API.

Steve
 
M

MG

Steve Horsley said:
And if read() keeps on immediately returning -1? Read the API.

Steve

You got me there! I converted the code from a "read(oneByte, 0, 1)"
to a simple "read()" and forgot to add the -1 detection. As it turned
out the "oneByte" reading approach looks better anyway since "read()"
appears to allocate a byte array each time it is called, so it's a
waste to use it anyway.

Thanks for the tip.

Mark
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top