United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4887178 in with J2se1.3 in multithread situation, socket reads data unexpectly
JDK-4887178 : in with J2se1.3 in multithread situation, socket reads data unexpectly

Details
Type:
Bug
Submit Date:
2003-07-08
Status:
Closed
Updated Date:
2009-06-25
Project Name:
JDK
Resolved Date:
2003-11-03
Component:
core-libs
OS:
solaris_8
Sub-Component:
java.net
CPU:
sparc
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.3.1
Fixed Versions:
1.3.1_11 (11)

Related Reports
Backport:
Backport:
Backport:

Sub Tasks

Description
escalationID is 547065
My ISV experiences the below problem as below

testcase is in SocketBug.jar
start server from ost.ServerSimulator
start client from ost.ClientSimuator

BUG : in multithreads situation, socket improperly reads data instead of 
blocking read or throw exceptions, although lock is designed properly.
 
Platform: J2SE1.3
                         
Senario:
The bug is reproducible only with the setSOtimeout ,without an setSOtimeout 
there is no problem


First ServerSimulator  Threads generate many sockets in server side, pass those 
sockets to SocketReader Threads  and put SocketReaders  to a thread pool for 
reading 
also pass those sockets to  SocketCloser threads groups for closing sockets by 
putting socketcloser threads into a same threadpool  and ServerSimuator Threads  
group will also setSoTimeout  for every
passed socket  , SocketReader thread read data from  inputstream completely, it 
will notfiy SocketCloser  thread to close this socket, then it trys to read 4 
bytes data again . at this moment
it should block at  p = in.read(data, 0, 4), because client doesnot send data 
again.
At this moment, socket could be closed or still open, if socket is closed by 
SocketCloser , then IOException should happen at p=in.read(data,0,4). if 
blocking time  expired, then also IOException will 
happen at p=in.read(data,0,4), but SocketReader should never be able to read any 
data at in.read(data,0,0,4), but in multi threads situation, it does read data 
unexpectedly.

                                    

Comments
EVALUATION

I modified the testcase to read 3 bytes in the second read() so as to distinguish the two 'read's. I analysed the system level calls made by the testcase using 'truss'. This is what is happening at the system level:

1336/11:        read(83, "\0010203", 4)                         = 4
...
1336/13:        close(83)                                       = 0
...
1336/6:         accept(6, 0xEE58153C, 0xEE58154C, 1)            = 83
...
1336/11:        read(83, "\00102", 3)                           = 3

Thread 11 reads 4 bytes in the first read call on the socket with fd 83 and notifies other thread to close this socket and proceeds to read 3 more bytes. Meanwhile Thread 13 closes that fd and creates another socket with same fd. Now Thread 11 reads 3 bytes on fd 83 as this is the first read after creation of fd 83 again. 

SocketInputStream class has an instance variable 'impl' of type PlainSocketImpl which contains an instance variable of type FileDescriptor (fd). SocketInputStream has methods to read and close the stream which in turn call the impl's methods to get the fd in read and set the fd to null in close.

Now here what could be happening is: While one thread is in the second read blocked at timeout, another thread closes the stream and sets the 'fd' of PlainSocketImpl to NULL and one another thread creates one more socket with the same file descriptor. Now when the first thread comes out from timeout(in the native), it does not know that the stream has been closed an it passes the old fd number to system read(). As this fd is valid (because it got recreated), read succeeds.

So the native call SocketRead() in SocketInputStream class and the close() method should be synchronized blocks. While one thread is in native SocketRead(), we should not allow other threads to close the stream and set fd to null. 


###@###.### 2003-07-28
                                     
2003-07-28
SUGGESTED FIX

Fix for 1.3.1 code base:

------- PlainSocketImpl.java -------
*** /tmp/sccs.J7aGol    Wed Aug 13 12:28:25 2003
--- PlainSocketImpl.java        Wed Aug 13 12:28:24 2003
***************
*** 508,513 ****
--- 508,516 ----
                synchronized(fdLock) {
                    if (fd != null) {
                        if (fdUseCount == 0) {
+                           if (closePending) {
+                               return;
+                           }
                            closePending = true;
                            socketClose(false);
                            fd = null;


###@###.### 2003-08-13

--- SocketInputStream.c Mon Oct 13 01:20:16 2003
*** 50,60 ****
      char *bufP;
      char BUF[MAX_BUFFER_LEN];
  
      jobject fdObj = (*env)->GetObjectField(env, this, sis_fdID);
!     jint fd, timeout;
  
      jobject impl = (*env)->GetObjectField(env, this, sis_implID);
  
      jint datalen, nread;
  
--- 50,60 ----
      char *bufP;
      char BUF[MAX_BUFFER_LEN];
  
      jobject fdObj = (*env)->GetObjectField(env, this, sis_fdID);
!     jint fd, timeout, newfd;
  
      jobject impl = (*env)->GetObjectField(env, this, sis_implID);
  
      jint datalen, nread;
  
*** 123,132 ****
--- 123,139 ----
            if (bufP != BUF) {
                free(bufP);
            }
            return -1;
        }
+ 
+         /*check if the socket has been closed while we were in timeout*/ 
+         newfd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+         if (newfd == -1) {
+             NET_ThrowSocketException(env, "Socket Closed");
+             return -1;
+         }   
      }
      nread = JVM_Recv(fd, bufP, len, 0);
      if (nread > 0) {
        (*env)->SetByteArrayRegion(env, data, off, nread, (jbyte *)bufP);
      } else {

###@###.### 2003-10-28
                                     
2003-10-28
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.3.1_11
1.4.1_07
1.4.2_04
generic
tiger-beta

FIXED IN:
1.3.1_11
1.4.1_07
1.4.2_04
tiger-beta

INTEGRATED IN:
1.3.1_11
1.4.1_07
1.4.2_04
tiger-b28
tiger-beta

VERIFIED IN:
1.3.1_11
1.4.1_07
1.4.2_04


                                     
2004-06-14



Hardware and Software, Engineered to Work Together