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