Duplicate :
|
Name: nt126004 Date: 03/06/2002 FULL PRODUCT VERSION : java version "1.4.0" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92) Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode) FULL OPERATING SYSTEM VERSION : Microsoft Windows 2000 [Version 5.00.2195] ADDITIONAL OPERATING SYSTEMS : A DESCRIPTION OF THE PROBLEM : NOTE: This seems to be a regression bug, since it worked correctly in Merlin-beta3 (build 1.4.0-beta3-b84). Since 1.4RC and now in 1.4.0, it is not working. When using a DatagramChannel is it not possible to asynchronously interrupt or close it. Accourding to the specifications, if interrupt() is called on the channel's thread, a java.nio.channels.ClosedByInterruptException should be thrown. And if the channel's close() method is called a java.nio.channels.AsynchronousCloseException should be called. Neither of these work. The thread dump of the sample program exhibithing this incorrect behaviour clearly shows that the DatagramChannel is blocked on a receive, and the main thread is blocked trying to kill it: Full thread dump Java HotSpot(TM) Client VM (1.4.0-b92 mixed mode): "Channel Thread" prio=5 tid=0x0AAFDA60 nid=0x2328 runnable [ae8f000..ae8fdb4] at sun.nio.ch.DatagramChannelImpl.receive0(Native Method) at sun.nio.ch.DatagramChannelImpl.receiveIntoNativeBuffer (DatagramChanne lImpl.java:173) at sun.nio.ch.DatagramChannelImpl.receive (DatagramChannelImpl.java:159) at sun.nio.ch.DatagramChannelImpl.receive (DatagramChannelImpl.java:116) - locked <02A06D08> (a java.lang.Object) at Client$1.run(Client.java:37) "Signal Dispatcher" daemon prio=10 tid=0x008E3620 nid=0x2354 waiting on monitor [0..0] "Finalizer" daemon prio=9 tid=0x0AA90D60 nid=0x2168 waiting on monitor [ad4f000. .ad4fdb4] at java.lang.Object.wait(Native Method) - waiting on <02A80138> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:111) - locked <02A80138> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:127) at java.lang.ref.Finalizer$FinalizerThread.run (Finalizer.java:159) "Reference Handler" daemon prio=10 tid=0x0AA90160 nid=0x2284 waiting on monitor [ad0f000..ad0fdb4] at java.lang.Object.wait(Native Method) - waiting on <02A801A0> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:426) at java.lang.ref.Reference$ReferenceHandler.run (Reference.java:113) - locked <02A801A0> (a java.lang.ref.Reference$Lock) "main" prio=5 tid=0x00234A10 nid=0x22fc waiting for monitor entry [6f000..6fc3c] at sun.nio.ch.DatagramChannelImpl.kill (DatagramChannelImpl.java:492) - waiting to lock <02A06D08> (a java.lang.Object) at sun.nio.ch.DatagramChannelImpl.implCloseSelectableChannel (DatagramCha nnelImpl.java:487) at java.nio.channels.spi.AbstractSelectableChannel.implCloseCha nnel(Abst ractSelectableChannel.java:202) at java.nio.channels.spi.AbstractInterruptibleChannel$1.interru pt(Abstra ctInterruptibleChannel.java:147) - locked <02A06CF0> (a java.lang.Object) at java.lang.Thread.interrupt(Thread.java:741) at Client.<init>(Client.java:60) at Client.main(Client.java:71) "VM Thread" prio=5 tid=0x0094F460 nid=0x2344 runnable "VM Periodic Task Thread" prio=10 tid=0x008E22D0 nid=0x2340 waiting on monitor "Suspend Checker Thread" prio=10 tid=0x008E2C60 nid=0x2360 runnable REGRESSION. Last worked in version 1.4 STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : USE JDK 1.4.0 1. Create a thread that opens a datagram channel and receives from it 2. From another thread attempt to close the channel or interrupt the thread 3. the threads lock: the datagram channel thread is blocked on i/o, and the other thread is blocked on trying to kill the channel Using the provided code, execute Client.java EXPECTED VERSUS ACTUAL BEHAVIOR : Depending on the closing method the expected results are: java.nio.channels.AsynchronousCloseException at java.nio.channels.spi.AbstractChannel.end (AbstractChannel.java:184) at sun.nio.ch.DatagramChannelImpl.receive (DatagramChannelImpl.java:140) at Client$1.run(Client.java:36) -or- java.nio.channels.ClosedByInterruptException at java.nio.channels.spi.AbstractChannel.end (AbstractChannel.java:183) at sun.nio.ch.DatagramChannelImpl.receive (DatagramChannelImpl.java:140) at Client$1.run(Client.java:37) Actual Results: -no exceptions- This bug can be reproduced always. ---------- BEGIN SOURCE ---------- //---- Client.java --- import java.nio.*; import java.nio.channels.*; import java.nio.charset.*; import java.net.*; public class Client { DatagramChannel channel; Client() { try { channel = DatagramChannel.open(); ByteBuffer buf = ByteBuffer.allocate(1000); buf.put("This is a datagram message".getBytes()); buf.flip(); final InetSocketAddress address = new InetSocketAddress ("225.100.10.101",8099); // send the datagram message channel.send(buf, address); // create a new thread the wait for the responses Thread t = new Thread() { private Charset charset = Charset.forName("US-ASCII"); private CharsetDecoder decoder = charset.newDecoder(); ByteBuffer buf2 = ByteBuffer.allocate(1000); public void run() { boolean interruptedOrClosed = false; // keep trying till this flag is set while(!interruptedOrClosed) { try { buf2.clear(); // even if we set the socket timeout, it doesn't work // channel.socket().setSoTimeout(2000); System.out.println("thread waiting to recieve..."); channel.receive(buf2); // if a server responds System.out.println("waiting thread received something"); buf2.flip(); System.out.println(decoder.decode(buf2).toString()); } catch(Exception e) { System.out.println("Some Exception"); // should be AsynchronousClose or ClosedByInterrupt // depending on call made below e.printStackTrace(); interruptedOrClosed = true; } } } }; // start the thread to wait for a response t.start(); // we will sleep and on awakening try to stop the waiting thread System.out.println("main thread sleeping for 2s"); Thread.sleep(2000); // either use the close() or interrupt() way, comment out one or the // other to see that both work. //System.out.println("attempting to close channel"); //channel.close(); System.out.println("attempting to interrupt inner thread"); t.interrupt(); } catch(Exception e) { e.printStackTrace(); } System.out.println("Main thread complete"); } public static void main (String[] args) { new Client(); } } //--- End of Client.java --- ============================================================================== // if you want to run the server, here is a quick server that // should respond once // -- Server.java -- import java.nio.*; import java.nio.channels.*; import java.nio.charset.*; import java.net.*; public class Server { MulticastSocket socket; private Charset charset = Charset.forName("US-ASCII"); private CharsetDecoder decoder = charset.newDecoder(); Server() { try { InetAddress group = InetAddress.getByName("225.100.10.101"); socket = new MulticastSocket(8099); socket.joinGroup(group); byte[] buf = new byte[1000]; DatagramPacket recv = new DatagramPacket(buf, buf.length); socket.receive(recv); System.out.println("Received: " + new String(recv.getData ()).trim()); InetAddress sender = recv.getAddress(); String reply = "This is a reply"; DatagramPacket send = new DatagramPacket(reply.getBytes(), reply.length() ,recv.getAddress(), recv.getPort()); socket.send(send); } catch(Exception e) { e.printStackTrace(); } } public static void main (String[] args) { new Server(); } } // -- End of Server.java -- ---------- END SOURCE ---------- CUSTOMER WORKAROUND : Not use latest version of 1.4, but keep using Merlin-beta3 Release Regression From : merlin-beta3 The above release value was the last known release where this bug was known to work. Since then there has been a regression. (Review ID: 139763) ======================================================================