[concurrency-interest] _interrupted field visibility bug in OpenJDK 7+

Ariel Weisberg ariel at weisberg.ws
Wed Nov 7 17:44:14 EST 2012


Hi,

I have no feedback other then than that it reproduced for me with with
SunJDK 1.6.0_31, Ubuntu 10.04, Intel i7-920.

With -Xint it worked.

I update to 1.6.0_37 and it still reproduced.

Regards,
Ariel



On Wed, Nov 7, 2012, at 05:00 PM, Dr Heinz M. Kabutz wrote:
> During a hands-on session today of my new Concurrency Specialist Course, 
> one of my students discovered what we think might be an interesting and 
> potentially serious bug in the JVM.  It seems that the Server HotSpot in 
> OpenJDK 7 may sometimes hoist the value of the _interrupted field.  This 
> is interesting, since the value is not stored in Java, but rather in the 
> OSThread.hpp file in the jint _interrupted field.  It is also pretty 
> serious, because it means we cannot rely on the interrupted status in 
> order to shut down threads.  This will affect Future.cancel(), 
> ExecutorService.shutdownNow() and a whole bunch of other mechanisms that 
> use interruptions to cooperatively cancel tasks.  (Obviously the 
> exercise was more involved than the code presented in this email, after 
> all the course is aimed at intermediate to advanced Java developers.  So 
> please don't expect that this won't happen in your code - I've just 
> taken away unnecessary code until we can see the bug without any of the 
> paraphernalia that might distract.)
> 
> First off, some code that works as expected.  As soon as you interrupt 
> the thread, it breaks out of the while() loop and exits:
> 
>     public void think() {
>         while (true) {
>             if (Thread.currentThread().isInterrupted()) break;
>         }
>         System.out.println("We're done thinking");
>     }
> 
> However, if you extract the "Thread.currentThread().isInterrupted()" 
> into a separate method, then that might be optimized by HotSpot to 
> always return false and the code then never ends:
> 
>     public void think() {
>         while (true) {
>             if (checkInterruptedStatus()) break;
>         }
>         System.out.println("We're done thinking");
>     }
> 
>     private boolean checkInterruptedStatus() {
>         return Thread.currentThread().isInterrupted();
>     }
> 
> My assumption is that the checkInterruptedStatus() method is 
> aggressively optimized and then the actual status is not read again.  
> This does not happen with the client hotspot and also not with Java 
> 1.6.0_37.  It does happen with the 1.8 EA that I've got on my MacBook 
> Pro.  The student was using a Windows machine, so this not just a Mac 
> problem. 
> 
> Here is the complete code:
> 
> public class InterruptedVisibilityTest {
>     public void think() {
>         while (true) {
>             if (checkInterruptedStatus()) break;
>         }
>         System.out.println("We're done thinking");
>     }
> 
>     private boolean checkInterruptedStatus() {
>         return Thread.currentThread().isInterrupted();
>     }
> 
>     public static void main(String[] args) throws InterruptedException {
>         final InterruptedVisibilityTest test =
>                 new InterruptedVisibilityTest();
>         Thread thinkerThread = new Thread("Thinker") {
>             public void run() {
>                 test.think();
>             }
>         };
>         thinkerThread.start();
>         Thread.sleep(500);
>         thinkerThread.interrupt();
>         long timeOfInterruption = System.currentTimeMillis();
>         thinkerThread.join(500);
>         if (thinkerThread.isAlive()) {
>             System.err.println("Thinker did not shut down within 500ms");
>             System.err.println("Error in Java Virtual Machine!");
>             System.err.println("Interrupted: " + 
> thinkerThread.isInterrupted());
>             System.err.println();
>             System.err.println("(Let's see if the thread ever dies and 
> how long it takes)");
>             while (thinkerThread.isAlive()) {
>                 thinkerThread.join(1000);
>                 if (thinkerThread.isAlive()) {
>                     System.err.println("  ... still waiting");
>                 }
>             }
>         }
>         System.err.println("Finally, the thread has died - that took " +
>                 (System.currentTimeMillis() - timeOfInterruption) +
>                 "ms");
>     }
> }
> 
> As I said, the original code was more involved, but this demonstrates 
> the essentials.  I hope some of you might be able to take a look at 
> what's going on.
> 
> Regards
> 
> Heinz
> -- 
> Dr Heinz M. Kabutz (PhD CompSci)
> Author of "The Java(tm) Specialists' Newsletter"
> Sun Java Champion
> IEEE Certified Software Development Professional
> http://www.javaspecialists.eu
> Tel: +30 69 75 595 262
> Skype: kabutz
> 
> 
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest


More information about the Concurrency-interest mailing list