On 10/02/2013 09:31 PM, Martin Buchholz wrote:
>Objection. I can straightaway see a way of getting an instance of a JDK-8
>FutureTask with a runner that is not current running the FutureTask.run,
>without so much as needing a race. That would allow an adversary to to
>interrupt a thread in contravention of the security policy.
Interesting - FutureTask is designed to not make that possible - runner is
not exposed, and is supposed to be set only while executing the task.  Do
we have a bug?

Yes, the "bug" is in java.lang.Thread. Its inherent to the API for interrupt status handling. Thread has only one bit of information for interrupt status and one can not know whether the Thread.isInterrupted() == true is originating from Future.cancel(true) or some other legal interaction between the interrupted thread and some other interrupting thread. So FutureTask chooses not to clear the eventual interrupted status of the thread before it exits the run() method although it might have been interrupted by Future.cancel(true):

    /**
     * Ensures that any interrupt from a possible cancel(true) is only
     * delivered to a task while in run or runAndReset.
     */
    private void handlePossibleCancellationInterrupt(int s) {
        // It is possible for our interrupter to stall before getting a
        // chance to interrupt us.  Let's spin-wait patiently.
        if (s == INTERRUPTING)
            while (state == INTERRUPTING)
                Thread.yield(); // wait out pending interrupt

        // assert state == INTERRUPTED;

        // We want to clear any interrupt we may have received from
        // cancel(true).  However, it is permissible to use interrupts
        // as an independent mechanism for a task to communicate with
        // its caller, and there is no way to clear only the
        // cancellation interrupt.
        //
        // Thread.interrupted();
    }

So the thread might be left in interrupted state after the task has finished it's run() method. But I don't think it's possible to interrupt some thread via FutureTask.cancel(true) unless that thread has "recently" been executing the task's run() method.

Regards, Peter

Reply via email to