|
Quick Lists
|
|
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),
1.4(merlin-beta3) (Bug ID:2034687)
|
|
State
|
10-Fix Delivered,
Verified,
bug
|
|
Priority:
|
3-Medium
|
|
Related Bugs
|
4371159
,
4392428
,
4430840
,
4435342
,
4482812
,
4504764
,
4755503
,
4386498
|
|
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
|
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
|
|
|
 |