Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4344135
Votes 12
Synopsis Linux: close is not preemptive
Category java:classes_net
Reported Against 1.3 , 1.2.2 , 1.3.1 , ladybird , merlin-beta , merlin-beta2 , kestrel-linux , kest-linux-fcs
Release Fixed 1.3.1(ladybird-rc1)
State 10-Fix Delivered, Verified, bug
Priority: 3-Medium
Related Bugs 4371159 , 4386498 , 4392428 , 4430840 , 4435342 , 4482812 , 4504764 , 4755503
Submit Date 08-JUN-2000
Description





Test engr/net/UDPCloseTest from testbase_js suite fails due to the following reason:

The following test creates DatagramSocket and waits for data in the
child Thread ( setSoTimeout is set to 30 seconds).
Parent thread waits 4 seconds and closes the socket.
Test assumes that Socket closed exception should be thrown immediately after the socket
is closed but under

Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0beta-b07)
Java HotSpot(TM) Client VM (build 1.3.0beta-b04, mixed mode)
and
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0beta-b07)
Java HotSpot(TM) Server VM (build 1.3.0beta-b04, mixed mode)

Socket closed exception is thrown only when setSoTimeout period is expired.

Delay between socket is closed and exception is thrown is printed
to stdout. It should be about 4000 ( 4 seconds ).

This bug affects only client and server VM for linux.
Under classic VM this test passes.

--------------------------test.java-----------------
import java.net.*;
import java.io.*;

public class test extends Thread {

public static DatagramPacket p;
public static DatagramSocket s;
	public static void main (String[] a) {
		try {
				s = new DatagramSocket();
				byte[] recvbuf = new byte[200];
				p = new DatagramPacket(recvbuf, 200);
				Recv r = new Recv();
				(new Thread(r, "DGRecv thread#")).start();
			Thread.sleep(4000); // relinquish CPU for green threads....
         	        s.close();
			Thread.yield(); // relinquish green CPU...
		} catch (Exception e) { }
	}
}
class Recv extends Thread {
	public void run() {
      		long start = System.currentTimeMillis();
		try {
			test.s.setSoTimeout(30000);
			test.s.receive(test.p);
		} catch (IOException e) {
		    System.out.println("Exception: "+e);
			long delta = System.currentTimeMillis() - start;
			System.out.println("Delta="+delta);
		}
	}
}
-----------------------output------------------------------
Linux:

[ xxxxx@xxxxx -4 b]$ java -version
java version "1.3.0beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0beta-b07)
Java HotSpot(TM) Client VM (build 1.3.0beta-b04, mixed mode)
[ xxxxx@xxxxx -4 b]$ java test
Exception: java.net.SocketException: socket closed
Delta=30007
[ xxxxx@xxxxx -4 b]$ 

Solaris:

bash-2.00$ java -version
java version "1.3.0rc3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0rc3-Z)
Java HotSpot(TM) Client VM (build 1.3.0rc3-Z, interpreted mode)
bash-2.00$ java test
Exception: java.net.SocketException: socket closed
Delta=4009
bash-2.00$ 

--------------------------------------------------------------


======================================================================
Work Around
Extract from the 1.3.1 release note.
On Linux platforms, a thread that is waiting on an I/O operation will not wake
up if a file involved in the I/O operation is closed. This problem is being
tracked as bug 4344135. To avoid this problem, set the J2SE_PREEMPTCLOSE
environment variable to 1.

     J2SE_PREEMPTCLOSE=1
     export J2SE_PREEMPTCLOSE

 xxxxx@xxxxx  2001-05-31
Evaluation
This is very likely caused by the same problem on Solaris 5.6 or earlier. The close() system call on linux is not preemptive. This is the traditional unix semantics. There is solution in the solaris native hpi code, which is called CLOSEIO. It is locaed in file $(JDK_WS)/src/solaris/hpi/native_threads/src/sys_api_td.c

 xxxxx@xxxxx  2000-06-27

Close does not block on Linux as Hong assumed above.  Instead, if one thread is performing a select or poll (how I/O with timeout is handled in hotspot) and another thread attempts to close the socket that thread will return.  However, the first thread will not return with an error (as in Solaris).  Instead it will remain in the blocking call until the timeout has expired.

 xxxxx@xxxxx  2000-07-24

The fix for this bug is the same as the blocking semantics of close under
Solaris  (and AIX).  You must keep a list associated with each fd which
records threads which are performing blocking IO on it.  Then, when the
thread is closed a signal must be sent to the threads.  In the case of Solaris,
this is necessary to stop the close blocking.  Under Linux, this is necessary
to pre-empt the threads else they will remain in the calls after the close.

This quite a large change and could introduce other problems into the VM and
therefore will be postponed to Merlin.

 xxxxx@xxxxx  2000-08-09

Using CLOSEIO for native threads classic VM does workaround one reported 
failure in regards to RMI, included that bug reports test case in attachments
(from bug 4392428)




 xxxxx@xxxxx  2001-01-04

The upcoming 2.4.0 kernel release has a *partial* solution for this problem.
It is now possible to call `shutdown(fd, 2)' before `close()':
it will return -ENOTCONN (as per POSIX) for listening/unconnected
sockets, *but* anyone doing a poll will receive POLLHUP anyway.  This
should make the workaround simpler, I assume.

 xxxxx@xxxxx  2001-01-08


Shutdown is already exposed in Java APIs via Socket.shutdownInput
& Socket.shutdownOutput methods.

However shutdown ignores the linger setting and always performs
a graceful shutdown. This might result in unexpected wire level
behaviour if the application has set the linger setting.

It seems for now that the closable IO workaround that was done
for the Solaris 2.5.1 kernel is appropriate to re-introduce
for Linux until there is a better solution found.

 xxxxx@xxxxx  2001-01-26


This has been fixed for beta3. Specifically :-

Socket.close will cause any other thread blocked in connect(),
getInputStream().read(), getOutputStream.write() on that socket
to throw a SocketException.

ServerSocket.close will cause any thread block in accept() on 
that socket to throw a SocketException.

DatagramSocket.close will cause any thread blocked in
receive() on that socket to throw a SocketException.

 xxxxx@xxxxx  2001-09-19
Comments
  
  Include a link with my name & email   

Submitted On 05-FEB-2001
jbcs
Unfortunately our testing of Java version 1.3.0 under Linux 
reveals that the Socket methods shutdownInput() and 
shutdownOutput() are having no effect and the host to which 
we opened the socket still thinks we are connected.
Can any one confirm if this is also a problem in AIX ?
as the final solution we have to deliver to the customer
will be running on AIX.
Any other work around suggestions other than the obvious
one of re-using the socket ?


Submitted On 15-FEB-2001
parna
In test.java if the line 
        test.s.setSoTimeout(30000);
is commented out then the revieve never throws an 
expection. This causes the thread to be blocked forever.
This happens only in JDK1.3 under linux else everywhere the 
excpetion is recieved.




Submitted On 23-DEC-2001
Paulfrance
lol


Submitted On 13-FEB-2002
brett_humphreys
I seems that this workaround does not work with JDK 
1.3.1_02, but does work with JDK 1.3.1_01.  The 
J2SE_PREEMPT seems to have no effect in the former, but 
with the latter, it works as advertised.


Submitted On 09-JUL-2002
anivard
jdk1.3.1_04 =>
Exception: java.net.SocketException: socket closed
Delta=4009
jdk1.4.0_01 =>
Exception: java.net.SocketException: Socket closed
Delta=4017
The workarround is not working... The UDP(corba process)
have to work on linux; I have no problem on Solaris and AIX


Submitted On 12-NOV-2003
thangaprakash
This work around solutions work fine.. in redhat 7.2  JDK.1.3.1
But setting J2SE_PREEMPTCLOSE gives some other problem..
when i tried to invoke konqueror from the java application ..
This gives me an error ..
Without setting this, konqueror is invoked successfully  but
the socket problem exists...
please... help me if there is any other alternatives..


Submitted On 19-MAR-2005
yeahzy
ls


Submitted On 19-MAR-2005
yeahzy
yeahzy



PLEASE NOTE: JDK6 is formerly known as Project Mustang