Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InternalCallbackExecutor does not handle failures properly #8069

Closed
scabug opened this issue Dec 11, 2013 · 5 comments
Closed

InternalCallbackExecutor does not handle failures properly #8069

scabug opened this issue Dec 11, 2013 · 5 comments
Assignees
Labels
Milestone

Comments

@scabug
Copy link

scabug commented Dec 11, 2013

As reported in https://twitter.com/crichardson/status/391689178146418688 the following

scala.concurrent.Future{1} zip null

fails with :

java.lang.IllegalStateException: problem in scala.concurrent internal callback
	at scala.concurrent.Future$InternalCallbackExecutor$.reportFailure(Future.scala:589)
	at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
	at scala.concurrent.impl.Promise$DefaultPromise.scala$concurrent$impl$Promise$DefaultPromise$$dispatchOrAddCallback(Promise.scala:280)
	at scala.concurrent.impl.Promise$DefaultPromise.onComplete(Promise.scala:270)
	at scala.concurrent.Future$class.zip(Future.scala:361)
	at scala.concurrent.impl.Promise$DefaultPromise.zip(Promise.scala:153)
	at org.backuity.photo.IndexerTest.ff(IndexerTest.scala:34)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:202)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:65)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.IllegalArgumentException: requirement failed
	at scala.Predef$.require(Predef.scala:221)
	at scala.concurrent.Future$InternalCallbackExecutor$Batch.run(Future.scala:628)
	at scala.concurrent.Future$InternalCallbackExecutor$.scala$concurrent$Future$InternalCallbackExecutor$$unbatchedExecute(Future.scala:691)
	at scala.concurrent.Future$InternalCallbackExecutor$Batch$$anonfun$run$1.processBatch$1(Future.scala:649)
	at scala.concurrent.Future$InternalCallbackExecutor$Batch$$anonfun$run$1.apply$mcV$sp(Future.scala:655)
	at scala.concurrent.Future$InternalCallbackExecutor$Batch$$anonfun$run$1.apply(Future.scala:632)
	at scala.concurrent.Future$InternalCallbackExecutor$Batch$$anonfun$run$1.apply(Future.scala:632)
	at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72)
	at scala.concurrent.Future$InternalCallbackExecutor$Batch.run(Future.scala:631)
	at scala.concurrent.Future$InternalCallbackExecutor$.scala$concurrent$Future$InternalCallbackExecutor$$unbatchedExecute(Future.scala:691)
	at scala.concurrent.Future$InternalCallbackExecutor$.execute(Future.scala:682)
	... 32 more

I took a quick look at it and this code seems suspicious (from 2.10.3 Future l.642):

 case t: Throwable =>
                    // if one task throws, move the
                    // remaining tasks to another thread
                    // so we can throw the exception
                    // up to the invoking executor
                    val remaining = _tasksLocal.get
                    _tasksLocal set Nil
                    unbatchedExecute(new Batch(remaining))
                    throw t

The new Batch, executed in the same thread, will see non null _tasksLocal and fail, swallowing exception t.

@scabug
Copy link
Author

scabug commented Dec 11, 2013

Imported From: https://issues.scala-lang.org/browse/SI-8069?orig=1
Reporter: Bruno Bieth (mustaghattack)

@scabug
Copy link
Author

scabug commented Jun 27, 2014

@retronym said:
Related investigation: https://github.com/scala/scala/pull/3827/files

@scabug
Copy link
Author

scabug commented Aug 5, 2014

@gkossakowski said:
The 2.11.2 is out so I'm rescheduling the issue for 2.11.3.

@scabug
Copy link
Author

scabug commented Nov 4, 2014

@retronym said:
Updating fix-by version to 2.11.5.

@scabug
Copy link
Author

scabug commented Nov 18, 2014

@jedesah said:
What is the expected behavior?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants