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

Future.foreach throws scala.actors.SuspendActorControl #5574

Closed
scabug opened this Issue Mar 15, 2012 · 6 comments

Comments

Projects
None yet
2 participants
@scabug
Copy link

scabug commented Mar 15, 2012

Minimized test-case:

object Temp extends App{
  val fut = scala.actors.Futures.future({ Thread.sleep(1000) ; 1 + 1 })
  fut.foreach( println _ )
}

$ scala -cp . t5574.scala
scala.actors.SuspendActorControl

Old description follows.

Doing this in the repl:

val fut = scala.actors.Futures.future({ Thread.sleep(1000) ; 1 + 1 })
fut.foreach( println _ )

results in:

 scala.actors.ActorProxy@5629fbc9: caught java.lang.InterruptedException
java.lang.InterruptedException
        at scala.actors.ActorProxy.exit(ActorProxy.scala:32)
        at scala.actors.Reactor$$anonfun$2.apply(Reactor.scala:267)
        at scala.actors.Reactor$$anonfun$2.apply(Reactor.scala:267)
        at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
        at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
        at scala.actors.ReactorTask.run(ReactorTask.scala:41)
        at scala.actors.Reactor$class.resumeReceiver(Reactor.scala:129)
        at scala.actors.ActorProxy.scala$actors$ReplyReactor$$super$resumeReceiver(ActorProxy.scala:20)
        at scala.actors.ReplyReactor$class.resumeReceiver(ReplyReactor.scala:68)
        at scala.actors.ActorProxy.resumeReceiver(ActorProxy.scala:20)
        at scala.actors.Actor$class.searchMailbox(Actor.scala:500)
        at scala.actors.ActorProxy.searchMailbox(ActorProxy.scala:20)
        at scala.actors.Reactor$$anonfun$startSearch$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(Reactor.scala:117)
        at scala.actors.Reactor$$anonfun$startSearch$1$$anonfun$apply$mcV$sp$1.apply(Reactor.scala:114)
        at scala.actors.Reactor$$anonfun$startSearch$1$$anonfun$apply$mcV$sp$1.apply(Reactor.scala:114)
        at scala.actors.ReactorTask.run(ReactorTask.scala:33)
        at scala.concurrent.forkjoin.ForkJoinPool$AdaptedRunnable.exec(ForkJoinPool.java:611)
        at scala.concurrent.forkjoin.ForkJoinTask.quietlyExec(ForkJoinTask.java:422)
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.mainLoop(ForkJoinWorkerThread.java:340)
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:325)

Problem was mentioned here: http://www.scala-lang.org/node/9298

I think the problem is this:

foreach defined in scala.Responder:

def foreach(k: A => Unit) { respond(k) }

Future respond() is:

  def respond(k: T => Unit) {
    if (isSet) k(fvalueTyped)
    else {
      val ft = this !! Eval
      ft.inputChannel.react {
        case _ => k(fvalueTyped)
      }
    }
  }

When the Future is not set foreach calls react on the input channel, which calls react back on the future. In Reactor.scala line 200:

 protected def react(handler: PartialFunction[Msg, Unit]): Nothing = {
    synchronized { drainSendBuffer(mailbox) }
    searchMailbox(mailbox, handler, false)
    throw Actor.suspendException
  }

See also: #3458

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 15, 2012

Imported From: https://issues.scala-lang.org/browse/SI-5574?orig=1
Reporter: Joseph Shraibman (jks)
Affected Versions: 2.9.1, 2.10.0-M3

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 22, 2012

Joseph Shraibman (jks) said:
Setting scala.control.noTraceSuppression and changing suspendException to a def (rather than a val) I get:

scala.actors.SuspendActorControl
        at scala.actors.SuspendActorControl.scala$util$control$NoStackTrace$$super$fillInStackTrace(Actor.scala:872)
        at scala.util.control.NoStackTrace$class.fillInStackTrace(NoStackTrace.scala:21)
        at scala.actors.SuspendActorControl.fillInStackTrace(Actor.scala:872)
        at java.lang.Throwable.<init>(Throwable.java:181)
        at scala.actors.SuspendActorControl.<init>(Actor.scala:872)
        at scala.actors.Actor$.suspendException(Actor.scala:54)
        at scala.actors.Actor$class.searchMailbox(Actor.scala:453)
        at scala.actors.ActorProxy.searchMailbox(ActorProxy.scala:19)
        at scala.actors.Reactor$class.react(Reactor.scala:202)
        at scala.actors.ActorProxy.scala$actors$ReplyReactor$$super$react(ActorProxy.scala:19)
        at scala.actors.ReplyReactor$class.react(ReplyReactor.scala:108)
        at scala.actors.ActorProxy.scala$actors$Actor$$super$react(ActorProxy.scala:19)
        at scala.actors.Actor$class.react(Actor.scala:598)
        at scala.actors.ActorProxy.react(ActorProxy.scala:19)
        at scala.actors.Channel.react(Channel.scala:76)
        at scala.actors.FutureActor.respond(Future.scala:64)
        at scala.Responder.foreach(Responder.scala:71)
        at $line3.$read$$iw$$iw$.liftedTree1$1(<console>:9)
        at $line3.$read$$iw$$iw$.<init>(<console>:9)
        at $line3.$read$$iw$$iw$.<clinit>(<console>)
        at $line3.$eval$.<init>(<console>:7)
        at $line3.$eval$.<clinit>(<console>)
        at $line3.$eval.$print(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:758)
        at scala.tools.nsc.interpreter.IMain$Request$$anonfun$13.apply(IMain.scala:990)
        at scala.tools.nsc.interpreter.Line.scala$tools$nsc$interpreter$Line$$runAndSetState(Line.scala:41)
        at scala.tools.nsc.interpreter.Line$$anonfun$2.apply$mcV$sp(Line.scala:47)
        at scala.tools.nsc.io.package$$anon$2.run(package.scala:19)
        at java.lang.Thread.run(Thread.java:662)
@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 22, 2012

Joseph Shraibman (jks) said:
Changing suspendException to a def isn't actually necessary. Just starting the repl with -Dscala.control.noTraceSuppression=true is enough.

That stack trace was from the current git head btw. The stack trace generated by 2.9.1 looks slightly different.

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 27, 2012

@adriaanm said:
not sure whether this is mostly repl or mostly actor, so, please re-assign if it's mostly REPL

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 27, 2012

Joseph Shraibman (jks) said:
I originally encountered this in real code, and this is easy to reproduce with compiled code.

object Temp extends App{

val fut = scala.actors.Futures.future({ Thread.sleep(1000) ; 1 + 1 })
fut.foreach( println _ )

}
@scabug

This comment has been minimized.

Copy link
Author

scabug commented Dec 13, 2012

@adriaanm said:
actors have migrated

@scabug scabug closed this Dec 13, 2012

@scabug scabug added this to the 2.10.1 milestone Apr 7, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment