JDK-6596323 : (fc) ClosedByInterruptException not thrown by the interrupt method (lnx)
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2007-08-23
  • Updated: 2011-05-18
  • Resolved: 2011-05-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 Other
6u10Fixed 7 b30Fixed OpenJDK6Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_02"
Java(TM) SE Runtime Environment (build 1.6.0_02-b05)
Java HotSpot(TM) Client VM (build 1.6.0_02-b05, mixed mode, sharing)


ADDITIONAL OS VERSION INFORMATION :
Linux hostname 2.6.17-11-386 #2 Fri May 18 23:37:00 UTC 2007 i686 GNU/Linux

Ubuntu 6.10

A DESCRIPTION OF THE PROBLEM :
I have implemented a timeout for the thread blocking on the I/O operation using InterruptableChannel interface. It works just fine with jdk 1.5.0_10. The ClosedByInterruptException is thrown and caught (please see the sample code below)
However, on Java 6 it seems like the the blocked thread never receives the ClosedByInterruptException.

If the read is attempeted after the interrupt then the ClosedChannelException is thrown and the thread is stopped. However if no read happens the thread blocks for ever.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the code provided below.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Start
user input
Read line:'user input'
INTERRUPTING
LEAVING java.nio.channels.ClosedByInterruptException

ACTUAL -
Start
user input 1
Read line:'user input 1'
INTERRUPTING


However if I try yet another "user input" AFTER the interrupt, I get:

Start
user input
Read line:'user input'
INTERRUPTING
user input 2
Read line:'user input 2'
LEAVING java.nio.channels.ClosedChannelException


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.BufferedReader;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.channels.Channels;

public class InterruptInput {
    
    public static void main(String args[]) {
        try {
        	
        	BufferedReader in = new BufferedReader(
                    new InputStreamReader(
                    Channels.newInputStream(
                    (new FileInputStream(FileDescriptor.in)).getChannel())));
            
            System.out.println("Start");
            // interrupt input in 10 sec
            (new TimeOut()).start();
            String line = null;
            while ((line = in.readLine()) != null) {
                System.out.println("Read line:'"+line+"'");
            }
        } catch (Exception ex) {
            System.out.println("LEAVING " + ex.toString());
        }
    }
    
    public static class TimeOut extends Thread {
        
        Thread threadToInterrupt = null;
        public TimeOut() {
            // interrupt thread that creates this TimeOut.
            threadToInterrupt = Thread.currentThread();
            setDaemon(true);
        }
        
        public void run() {
            try {
                sleep(10000);
            } catch(InterruptedException ex) {/*ignore*/}
            System.out.println("INTERRUPTING");
            threadToInterrupt.interrupt();
        }
    }
}
---------- END SOURCE ----------

Release Regression From : 5.0
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Comments
SUGGESTED FIX $ diff -r cbd182c404d8 src/share/classes/sun/nio/ch/NativeThreadSet.java --- a/src/share/classes/sun/nio/ch/NativeThreadSet.java Fri May 23 11:13:45 2008 -0700 +++ b/src/share/classes/sun/nio/ch/NativeThreadSet.java Thu May 29 16:13:26 2008 +0100 @@ -43,7 +43,7 @@ class NativeThreadSet { // int add() { long th = NativeThread.current(); - if (th <= 0) + if (th == -1) return -1; synchronized (this) { int start = 0; diff -r cbd182c404d8 src/solaris/classes/sun/nio/ch/NativeThread.java --- a/src/solaris/classes/sun/nio/ch/NativeThread.java Fri May 23 11:13:45 2008 -0700 +++ b/src/solaris/classes/sun/nio/ch/NativeThread.java Thu May 29 16:13:26 2008 +0100 @@ -41,7 +41,7 @@ class NativeThread { // Returns an opaque token representing the native thread underlying the // invoking Java thread. On systems that do not require signalling, this - // method always returns zero. + // method always return -1. // static native long current(); diff -r cbd182c404d8 src/windows/classes/sun/nio/ch/NativeThread.java --- a/src/windows/classes/sun/nio/ch/NativeThread.java Fri May 23 11:13:45 2008 -0700 +++ b/src/windows/classes/sun/nio/ch/NativeThread.java Thu May 29 16:13:26 2008 +0100 @@ -31,7 +31,7 @@ package sun.nio.ch; class NativeThread { - static long current() { return 0; } + static long current() { return -1; } static void signal(long nt) { } diff -r cbd182c404d8 test/java/nio/channels/AsyncCloseAndInterrupt.java --- a/test/java/nio/channels/AsyncCloseAndInterrupt.java Fri May 23 11:13:45 2008 -0700 +++ b/test/java/nio/channels/AsyncCloseAndInterrupt.java Thu May 29 16:13:26 2008 +0100 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4460583 4470470 4840199 6419424 + * @bug 4460583 4470470 4840199 6419424 6596323 * @summary Comprehensive test of asynchronous closing and interruption * @author Mark Reinhold */
29-05-2008

EVALUATION The plan is to fix this in jdk7 and let it bake for a while before considering it for a jdk6 update.
23-05-2008

EVALUATION The regression is also why there is a difference between the "spec" and implementation as observed by Martin here: http://mail.openjdk.java.net/pipermail/core-libs-dev/2008-April/000317.html That is, the original intent was the thread id was to be used to signal a blocked thread on Linux. The changes in 6285901 change the semantics so that a non-zero value means there is a reader or writer thread.
06-04-2008

EVALUATION There is indeed a regression here. The close mechanism records the thread ID of threads doing I/O so they can be interrupted. It appears the changes for 6285901 changed this so that negative thread IDs are not recorded. This bug has gone unnoticed because a read from a FileChannel does not normally block indefinitely.
23-08-2007