MacOS FutureTask.get race

Jason Schroeder shrode at subnature.com
Mon Oct 31 08:07:54 PDT 2011


I hope mentioning the race contained in this example is appropriate.  I can
only force this bug to appear with the MacOS jvm.

How can I be of useful assistance?

// $ java -version
// java version "1.6.0_27"
// Java(TM) SE Runtime Environment (build 1.6.0_27-b07-393-11M3511)
// Java HotSpot(TM) 64-Bit Server VM (build 20.2-b06-393, mixed mode)
//
// This an example of the error:
//
// error:gingerbreadman1509143 != null != gingerbreadman1509143
//
// An InvertedFuture object implementing Callable is given to the
ScheduledExecutorService
// and the second Future object returned by the ScheduledExecutorService is
ignored.
//
// It seems the InvertedFuture's get method is unblocking moments too early
to return a null
// object, impossible under the contract for the methods involved, and then
returns the second
// and expected value moments after that.
//
// This code pattern is inspired by how ExecutorService and
CompletionService are implemented
// in the JDK.

import java.util.concurrent.*;

public class RacebugTest  {

    public static int ITERATIONS = 10000*1000;

    public static void main(String[]args) throws ExecutionException,
InterruptedException {
        ScheduledExecutorService ses = Executors.newScheduledThreadPool(3,
Executors.defaultThreadFactory());

        Callable callable;

        for(int i = 0;i<ITERATIONS;i++) {
            callable = new DoNothing("gingerbreadman" + i);

            InvertedFuture future = new InvertedFuture (callable);
            Future ignored = ses.submit((Callable)future);

            String comparison = ("gingerbreadman" + i);
            Object result = future.get();

            // Not only is this condition possible with result == null
            if (! comparison.equals(result)) {
                // But a second attempt to access Future.get() results in a
second value with the expected result
                System.out.println ("error:" + comparison + " != " + result
+ " != " + future.get());
                System.exit(1);
            }
        }
    }

    protected static class InvertedFuture extends FutureTask implements
Callable {
        private final Callable callable;

        InvertedFuture(Callable callable) {
            super(callable);
            this.callable = callable;
        }

        @Override
        public Object call() throws Exception {
            Object result;
            try {
                result = callable.call();
                set(result);
                return result;
            } catch (Error e) {
                setException(e);
                throw e;
            } catch (Exception e) {
                setException(e);
                throw e;
            }
        }
    }

    static class DoNothing implements Callable {
        Object result;
        DoNothing(Object result) {
            this.result = result;
        }
        @Override
        public Object call() throws Exception {
            return result;
        }
    }
}


More information about the macosx-port-dev mailing list