[Fwd: _interrupted field visibility bug in OpenJDK 7+]

Vladimir Kozlov vladimir.kozlov at oracle.com
Wed Nov 7 22:24:15 PST 2012


Thank you, Heinz

Yes, we are looking on this problem.

Regards,
Vladimir

On Nov 7, 2012, at 10:07 PM, Dr Heinz M. Kabutz wrote:

> In case you have not seen, there is a discussion on concurrency-interest (http://tinyurl.com/bofu46j) about a new bug that we discovered where code dealing with isInterrupted() is not correctly optimized, leading to issues where a thread does not see its interrupted status change.
> 
> This has been submitted as a bug
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8003135
> 
> 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 
> 
> From: "Dr Heinz M. Kabutz" <heinz at javaspecialists.eu>
> Subject: _interrupted field visibility bug in OpenJDK 7+
> Date: November 7, 2012 2:00:06 PM PST
> To: concurrency-interest at cs.oswego.edu
> 
> 
> 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
> 
> 
> 
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20121107/a15226d9/attachment-0001.html 


More information about the hotspot-compiler-dev mailing list