Closed scabug closed 10 years ago
Imported From: https://issues.scala-lang.org/browse/SI-8377?orig=1 Reporter: Niklas Nebel (niklasn) Affected Versions: 2.10.3, 2.11.0-RC1
@retronym said: Recent mailing list thread discussing why an immediate (ie current thread) execution context can be problematic: https://groups.google.com/forum/#!msg/scala-user/lVFde4UyBvc/lml-BkIGQuYJ
@retronym said: /cc @viktorklang
Viktor Klang (viktorklang) said: implicit val immediateContext = new scala.concurrent.ExecutionContext { override def execute(runnable: Runnable) { runnable.run() } override def reportFailure(t: Throwable) { t.printStackTrace() } }
This is not a valid execution context. We will update the documentation to explain that ECs must be async to be general purpose—i.e. you can only use the construct above to execute your own code.
Viktor Klang (viktorklang) said: See this discussion for more background: https://groups.google.com/forum/#!searchin/scala-user/Future$20$26$20ExecutionContext/scala-user/LKiVD2PGvew/XDT-UZrAjJcJ
Viktor Klang (viktorklang) said: https://github.com/scala/scala/pull/3613
@nilskp said: Any chance this can make it into 2.10.4?
@retronym said: 2.10.4 final has already been cut. We'd accept a pull request that cherry-picks the doc fix to the 2.10.x branch. That would be included in 2.10.5.
The following example uses an ExecutionContext with direct, synchronous execution.
It fails with
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.blockOn(Future.scala:669) at scala.concurrent.Await$.ready(package.scala:86) at $anonfun$3.apply(:17)
at $anonfun$3.apply(:15)
at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:251)
at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:249)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at $anon$1.execute(:10)
at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248)
at scala.concurrent.Promise$class.complete(Promise.scala:55)
at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153)
at scala.concurrent.Future$$anonfun$flatMap$1$$anonfun$apply$3.apply(Future.scala:254)
at scala.concurrent.Future$$anonfun$flatMap$1$$anonfun$apply$3.apply(Future.scala:254)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at scala.concurrent.Future$InternalCallbackExecutor$Batch$$anonfun$run$1.processBatch$1(Future.scala:640)
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)
at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
at scala.concurrent.impl.Promise$KeptPromise.onComplete(Promise.scala:333)
at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:254)
at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:249)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at $anon$1.execute(:10)
at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248)
at scala.concurrent.Promise$class.complete(Promise.scala:55)
at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:23)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
The stack trace is from 2.10.3, but it also fails in 2.11.0-RC1. The stack strace looks very similar to that of #8069. Batch#blockOn looks suspicious, setting _tasksLocal to Nil and then calling run which requires it to be null. Also the "WARNING" comment from BatchingExecutor seems to apply to InternalCallbackExecutor.