Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8269467

Cancelled FutureTask's interrupt may leak

      A DESCRIPTION OF THE PROBLEM :
      Cancelled FutureTask's interrupt may leak

      Use ScheduledThreadPoolExecutor to run period task.

      A worker called W (according to Thread T1) in the ScheduledThreadPoolExecutor has got the FutureTask called T1, it is executing the `runAndReset()` method. It just run after the `s = state;` sentence, so the variable `s` equals `0` representing the `NEW` state. It is worth noting that the `runner = null;` sentence has not been executed because of instructions reorder.

      At the moment, another Thread T2 invoke the `cancel(true)` method of T1, it continues to execute when the `UNSAFE.compareAndSwapInt(this, stateOffset, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)` sentence returns true until the `if (t != null)` sentence with the variable `Thread t` equals to `T1`, then it hangs.


      W continues to run which passes the `handlePossibleCancellationInterrupt` sentence because of `if (s >= INTERRUPTING)` returning false and gets another FutureTask called FT2 after some time.
      So if T2 interrupts the T1 at the time, FT2 may be affected.



           public boolean cancel(boolean mayInterruptIfRunning) {
              if (!(state == NEW && STATE.compareAndSet
                    (this, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
                  return false;
              try { // in case call to interrupt throws exception
                  if (mayInterruptIfRunning) {
                      try {
                          Thread t = runner;
                          if (t != null)
                              t.interrupt();
                      } finally { // final state
                          STATE.setRelease(this, INTERRUPTED);
                      }
                  }
              } finally {
                  finishCompletion();
              }
              return true;
          }
          
          
          
          
          protected boolean runAndReset() {
              if (state != NEW ||
                  !RUNNER.compareAndSet(this, null, Thread.currentThread()))
                  return false;
              boolean ran = false;
              int s = state;
              try {
                  Callable<V> c = callable;
                  if (c != null && s == NEW) {
                      try {
                          c.call(); // don't set result
                          ran = true;
                      } catch (Throwable ex) {
                          setException(ex);
                      }
                  }
              } finally {
                  // runner must be non-null until state is settled to
                  // prevent concurrent calls to run()
                  runner = null;
                  // state must be re-read after nulling runner to prevent
                  // leaked interrupts
                  s = state;
                  if (s >= INTERRUPTING)
                      handlePossibleCancellationInterrupt(s);
              }
              return ran && s == NEW;
          }


            chegar Chris Hegarty
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated: