-
Bug
-
Resolution: Not an Issue
-
P1
-
None
-
2.0.1_build12, 2.0_beta24, 1.1, 1.1.4, 1.2.1
-
generic, x86, sparc
-
solaris_2.5.1, solaris_2.6, solaris_7, windows_95
[chamness 1/12/97] Update.
When running multiple threads, a thread that is invoking read()
on a socket can go to sleep. The other side of the socket
continues to write to this sleeping thread. The reading thread
eventually hangs. It can hang on a single byte read. So while reading
an integer, it can get a corrupt value.
Setting the timeout period with Socket.setSoTimeout() will
cause the reading thread to throw an InterruptedIOException,
and get out of the hung state. But this is not a true
timeout.
If output streams are not buffered, windows 95 can crash.
======================================================================
Name: mc57594 Date: 02/14/97
First some background as to how we found this problem. We are
developing a client in Java which talks to a server. One of our
developers works from home and thus dials in over a slow line (28.8).
The java client sends a request to the server and then waits for a
reply. The connection is over a TCP socket. It is setup as:
try {
socket = new Socket(client.ip, client.port);
}
catch (UnknownHostException ex) {}
catch (IOException ex) { PtkUtil.PtkcExit(client, "Can't create socket.", 1); }
try {
din = new DataInputStream(socket.getInputStream());
dout = new DataOutputStream(socket.getOutputStream());
}
catch (IOException ex) { PtkUtil.PtkcExit(client, "Can't create input/output stream.", 1); }
We used to receive our replies back using code like:
try {
size = _din.readShort();
version = _din.readInt();
...
} catch (IOException e) {
System.out.println("Reading header exception "+e);
return false;
}
return true;
Now normally this works just fine. We normally test the client and
server over an ethernet LAN and no problems. Today we had a developer
working from home and then tried the client/server connection over the
internet and 28.8K modem. We then encountered problems. The server
is attempting to send a client a 1460 byte response which is having
to be retransmitted multiple times (as seen with a #snoop).
Under JDK1.0.2, the client goes into the first
size = _din.readShort();
and never returns.
Under JDK1.1Beta3.3, the client goes into the first
size = _din.readShort();
and eventually goes to the catch block with
Reading header exception java.io.IOException: Resource temporarily unavailable
Our suspicion with JDK1.0.2 is that the read thread is going infinite
looping considering the response from JDK1.1Beta3.3. IE, it is catching
the exception and trying to deal with it but failing. In either case,
there really is data "in the pipe" so readShort() should not have failed;
the socket was not closed or broken.
I extracted the src.zip and looked in java/io/DataInputStream.java
at the readShort() function. It looks like:
public final short readShort() throws IOException {
InputStream in = this.in;
int ch1 = in.read();
int ch2 = in.read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (short)((ch1 << 8) + (ch2 << 0));
}
Unfortunately under JDK1.1Beta3 we get the IOException, but we don't know
which byte (ch1 or ch2) caused the exception. Thus we cannot easily
try again.
Under JDK1.1Beta3.3, you have socket.getTcpNoDelay() and
socket.getSoTimeout(). They are 'false' and '0' respectively.
----------
Instead of reading our data structure in a field at a time, I
decided to read in the entire header and then parse it apart. Normally
I would use readFully() for this. But we have the same problem with
readFully() and readShort(); IE, if we get an IOException we don't know
how much data has been read in so far. Thus we decided to come up with
our own readFully() function:
public static int readFully(DataInputStream in, byte [] b, int off, int len)
throws EOFException
{
int count;
int n = 0;
while (n < len) {
try {
System.out.println("readFully of "+(len-n)+" bytes at offset "+(
off+n));
count = in.read(b, off + n, len - n);
System.out.println("readFully count="+count);
}
catch (IOException e) {
/* Try again */
System.out.println("readFully: exception " + e);
continue;
}
if (count <= 0)
throw new EOFException();
n += count;
}
return n;
}
The idea here (based upon our developers experience) is that when an
IOException occurs to just ignore it and try again. In the one case
(slow link) we know there really is more data available. But, now
I cannot detect the differenence between EOF and a bad exception.
IE, if we enter this readFully() and actually close the socket, then
we get the same IOException:
readFully: exception java.io.IOException: Resource temporarily unavailable
as when the bytes were really temporarily unavailable. Now what?
In general it appears there is some edge condition where the various
blocking read*() calls are failing. In JDK1.0.2 they go infinite loop
(best guess since we never come out of the call) and in JDK1.1Beta3.3,
we get an "java.io.IOException: Resource temporarily unavailable" when
we should not. What is the fix?
======================================================================
When running multiple threads, a thread that is invoking read()
on a socket can go to sleep. The other side of the socket
continues to write to this sleeping thread. The reading thread
eventually hangs. It can hang on a single byte read. So while reading
an integer, it can get a corrupt value.
Setting the timeout period with Socket.setSoTimeout() will
cause the reading thread to throw an InterruptedIOException,
and get out of the hung state. But this is not a true
timeout.
If output streams are not buffered, windows 95 can crash.
======================================================================
Name: mc57594 Date: 02/14/97
First some background as to how we found this problem. We are
developing a client in Java which talks to a server. One of our
developers works from home and thus dials in over a slow line (28.8).
The java client sends a request to the server and then waits for a
reply. The connection is over a TCP socket. It is setup as:
try {
socket = new Socket(client.ip, client.port);
}
catch (UnknownHostException ex) {}
catch (IOException ex) { PtkUtil.PtkcExit(client, "Can't create socket.", 1); }
try {
din = new DataInputStream(socket.getInputStream());
dout = new DataOutputStream(socket.getOutputStream());
}
catch (IOException ex) { PtkUtil.PtkcExit(client, "Can't create input/output stream.", 1); }
We used to receive our replies back using code like:
try {
size = _din.readShort();
version = _din.readInt();
...
} catch (IOException e) {
System.out.println("Reading header exception "+e);
return false;
}
return true;
Now normally this works just fine. We normally test the client and
server over an ethernet LAN and no problems. Today we had a developer
working from home and then tried the client/server connection over the
internet and 28.8K modem. We then encountered problems. The server
is attempting to send a client a 1460 byte response which is having
to be retransmitted multiple times (as seen with a #snoop).
Under JDK1.0.2, the client goes into the first
size = _din.readShort();
and never returns.
Under JDK1.1Beta3.3, the client goes into the first
size = _din.readShort();
and eventually goes to the catch block with
Reading header exception java.io.IOException: Resource temporarily unavailable
Our suspicion with JDK1.0.2 is that the read thread is going infinite
looping considering the response from JDK1.1Beta3.3. IE, it is catching
the exception and trying to deal with it but failing. In either case,
there really is data "in the pipe" so readShort() should not have failed;
the socket was not closed or broken.
I extracted the src.zip and looked in java/io/DataInputStream.java
at the readShort() function. It looks like:
public final short readShort() throws IOException {
InputStream in = this.in;
int ch1 = in.read();
int ch2 = in.read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (short)((ch1 << 8) + (ch2 << 0));
}
Unfortunately under JDK1.1Beta3 we get the IOException, but we don't know
which byte (ch1 or ch2) caused the exception. Thus we cannot easily
try again.
Under JDK1.1Beta3.3, you have socket.getTcpNoDelay() and
socket.getSoTimeout(). They are 'false' and '0' respectively.
----------
Instead of reading our data structure in a field at a time, I
decided to read in the entire header and then parse it apart. Normally
I would use readFully() for this. But we have the same problem with
readFully() and readShort(); IE, if we get an IOException we don't know
how much data has been read in so far. Thus we decided to come up with
our own readFully() function:
public static int readFully(DataInputStream in, byte [] b, int off, int len)
throws EOFException
{
int count;
int n = 0;
while (n < len) {
try {
System.out.println("readFully of "+(len-n)+" bytes at offset "+(
off+n));
count = in.read(b, off + n, len - n);
System.out.println("readFully count="+count);
}
catch (IOException e) {
/* Try again */
System.out.println("readFully: exception " + e);
continue;
}
if (count <= 0)
throw new EOFException();
n += count;
}
return n;
}
The idea here (based upon our developers experience) is that when an
IOException occurs to just ignore it and try again. In the one case
(slow link) we know there really is more data available. But, now
I cannot detect the differenence between EOF and a bad exception.
IE, if we enter this readFully() and actually close the socket, then
we get the same IOException:
readFully: exception java.io.IOException: Resource temporarily unavailable
as when the bytes were really temporarily unavailable. Now what?
In general it appears there is some edge condition where the various
blocking read*() calls are failing. In JDK1.0.2 they go infinite loop
(best guess since we never come out of the call) and in JDK1.1Beta3.3,
we get an "java.io.IOException: Resource temporarily unavailable" when
we should not. What is the fix?
======================================================================
- relates to
-
JDK-4319848 Interrupted system call exception
-
- Closed
-
-
JDK-4283017 socketRead/socketWrite appears to hang
-
- Closed
-