Name: bsC130419 Date: 06/26/2001
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)
Contact Information
Computer Systems Research, Inc.
Custom software specialists
###@###.###
References
* Platform is Win32 (Windows 9x or NT/2K)
* MSDN article ID: Q201213
* Winsock error code 10055, WSAENOBUFS
* JDK 1.3.1 source code j2sdk1.3.1\src\win32
\native\java\net\SocketOutputStream.c, function
Java_java_net_SocketOutputStream_socketWrite
Background
I have been working on a project that requires client/server communications.
Multiple clients connect to a server and send lots of data to the server as
fast as possible. Intermittently, a client socket implemented with Java's
Socket class will throw an exception during an OutputStream.write. Embedded in
the exception's message string is code 10055. Under Win32, this error is
WSAENOBUFS which means the TCP/IP stack has temporarily run out of buffer space
and cannot complete the write. Microsoft has verified this as a bug in the
WinSock TCP/IP stack (see the MSDN article listed in the References section
above). This would be a recoverable error if not for the way the Java native
code handles the error. The recovery would simply be to wait for the stack
buffers to empty and try sending the same data again at a later time.
The problem arises from the Win32 Java source code breaking a buffer passed to
OutputStream.write into chunks (64K chunks if heap memory is available, 2K
chunks on the stack if not). The suspect native code is listed in the
References section above. Suppose I send a 128K buffer to OutputStream.write
and the native code successfully transmits the first 64K chunk but the second
64K chunk fails with error 10055. At this point, the native code throws a
SocketException but does not tell the caller how many bytes were written before
the error occurred. The caller does not know what part of the data stream
should be retransmitted.
Suggestion for Fix
A fix for this easy to implement. In the native source code at line 114,
instead of calling NET_ThrowCurrent, check the WSALastError code. If the code
is 10055, throw an InterruptedIOException with bytesTransferred set to the
variable loff. If the code is not 10055, handle it in the usual way by calling
NET_ThrowCurrent. The Java application can then handle the
InterruptedIOException and resume the transmission at the proper location.
This solution works because the JVM_send at line 105 for blocking sockets under
Win32 will either (1) send no data and return an error code or (2) send some or
all of the data and return the number of bytes sent.
Conclusion
This bug in Win32 can be easily handled in the Java native code. Hopefully,
this report is clear enough that a bug fix will be implemented soon.
(Review ID: 124911)
======================================================================