JDK-6772683 : Thread.isInterrupted() fails to return true on multiprocessor PC
  • Type: Bug
  • Status: Closed
  • Resolution: Fixed
  • Component: hotspot
  • Sub-Component: compiler
  • Priority: P4
  • Affected Version: 5.0-pool,6u10
  • OS: other,windows_vista
  • CPU: unknown,x86
  • Submit Date: 2008-11-18
  • Updated Date: 2015-01-30
  • Resolved Date: 2009-08-13
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 Availabitlity Release.

To download the current JDK release, click here.
Other JDK 6 JDK 7
5.0u21,hs14.2Fixed 6u16-revFixed 7Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
On Windows Vista 64-Bit:
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) 64-Bit Server VM (build 11.0-b15, mixed mode)

java version "1.5.0_16"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_16-b02)
Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_16-b02, mixed mode)

java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b39)
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b06, mixed mode)

On Linux Ubuntu 64-Bit:
java version "1.5.0_16"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_16-b02)
Java HotSpot(TM) Server VM (build 1.5.0_16-b02, mixed mode)

java version "1.5.0_16"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_16-b02)
Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_16-b02, mixed mode)

java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Server VM (build 11.0-b15, mixed mode)

java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) 64-Bit Server VM (build 11.0-b15, mixed mode)

java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b39)
Java HotSpot(TM) Server VM (build 14.0-b06, mixed mode)

java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b39)
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b06, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [version 6.0.6001] 64-Bit edition
Linux QuadCore 2.6.24-19-generic #1 SMP Wed Aug 20 17:53:40 UTC 2008 x86_64 GNU/Linux


EXTRA RELEVANT SYSTEM CONFIGURATION :
CPU: Q6600
memory: 4Gb


A DESCRIPTION OF THE PROBLEM :
While running two simultaneous threads, the first thread interrupts the second one using Thread.interrupt().
The second thread tests if it has been interrupted calling the Thread.isInterrupted() method which always returns false.

This occurs on a multiprocessor PC running a 64-Bit OS (Vista and Linux).
On Vista 64-Bit, this occurs when using a 64-bit JVM (all versions from 1.5 to 1.7), but does not occur when using a 32-bit JVM.
On Linux 64-bit, this occurs when using a 64-bit JVM (all versions from 1.5 to 1.7) or when using a 32-bit JVM (all versions from 1.5 to 1.7).


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. In the following program, the main thread creates a worker thread.
2. The worker thread enters in an infinite loop until it is interrupted. (calling the isInterrupted() method)
3. The main thread waits for the worker thread to die with a timeout of 1 second.
4. The main thread interrupts the worker thread and waits for it to die.
5. The worker thread continuously calls the isInterrupted() method that always return false whereas the thread is interrupted !


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The Thread.isInterrupted() method should return true and the worker thread should exit.
Here is output of the program executed with a 32-bit JVM on Vista 64-Bit:

Main thread: starts a worker thread...
Main thread: waits at most 1s for the worker thread to die...
Worker thread: running...
Main thread: interrupts the worker thread...
Worker thread: bye
Main thread: worker thread is interrupted
Main thread: waits for the worker thread to die...
Main thread: bye
ACTUAL -
The Thread.isInterrupted() method returns false and the worker thread never exit.
Here is output of the program executed with a 64-bit JVM on Vista 64-Bit:

Main thread: starts a worker thread...
Main thread: waits at most 1s for the worker thread to die...
Worker thread: running...
Main thread: interrupts the worker thread...
Main thread: worker thread is interrupted
Main thread: waits for the worker thread to die...

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class InterruptedTest {

    public static void main(String[] args) throws Exception {
        Thread workerThread = new Thread("worker") {
            public void run() {
                System.out.println("Worker thread: running...");
                while (!Thread.currentThread().isInterrupted()) {
                }
                System.out.println("Worker thread: bye");
            }
        };
        System.out.println("Main thread: starts a worker thread...");
        workerThread.start();
        System.out.println("Main thread: waits at most 1s for the worker thread to die...");
        workerThread.join(1000);
        if (workerThread.isAlive()) {
            System.out.println("Main thread: interrupts the worker thread...");
            workerThread.interrupt();
            if (workerThread.isInterrupted()) {
                System.out.println("Main thread: worker thread is interrupted");
            }
            System.out.println("Main thread: waits for the worker thread to die...");
            workerThread.join();
        }
        System.out.println("Main thread: bye");
    }

}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Calling Thread.yield() before Thread.isInterrupted() bypasses the bug.
Calling Thread.interrupted() instead of Thread.isInterrupted() bypasses the bug.

Comments
PUBLIC COMMENTS Problem: The C2 intrinsic isInterrupted() misses a control edge setting for the field thread::_interrupted load. The load use raw (not oop) thread pointer for which we don't generate a NULL check which prevents in an oop case the load to flow up. In the bug case the field load flow up from the loop and the field check follows it which is wrong. Solution: Set the control edge for the field _interrupted load.
2009-05-21

SUGGESTED FIX src/share/vm/opto/library_call.cpp @@ -2593,7 +2593,8 @@ bool LibraryCallKit::inline_native_isInt Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset())); - Node* int_bit = make_load(NULL, p, TypeInt::BOOL, T_INT); + // Set the control input on the field _interrupted read to prevent it floating up. + Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT); Node* cmp_bit = _gvn.transform( new (C, 3) CmpINode(int_bit, intcon(0)) ); Node* bol_bit = _gvn.transform( new (C, 2) BoolNode(cmp_bit, BoolTest::ne) );
2009-05-21

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/aabd393cf1ee
2009-05-21

EVALUATION C2 has an instrinic implementation of isInterrupt to avoid the call into the VM for the case that the receiver is the current thread. The issue is likely to be there as this doesn't duplicate with the client VM or with -Xint.
2009-05-19