Navigation Menu

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

IMain interpret does not reset context classloader #8521

Closed
scabug opened this issue Apr 21, 2014 · 9 comments
Closed

IMain interpret does not reset context classloader #8521

scabug opened this issue Apr 21, 2014 · 9 comments

Comments

@scabug
Copy link

scabug commented Apr 21, 2014

Calling interpret sets the current thread's context classloader, but fails to reset it to its previous state when returning from that method.

The following workaround illustrates the problem:

    val th = Thread.currentThread()
    val cl = th.getContextClassLoader
    try {
      imain.interpret(text)
    } finally {
      th.setContextClassLoader(cl)
    }

Jason Zaugg suggests that the following might be the regression: scala/scala@3a30af1#diff-36a995091016ecd5cdb97e267764e05aL538

@scabug
Copy link
Author

scabug commented Apr 21, 2014

Imported From: https://issues.scala-lang.org/browse/SI-8521?orig=1
Reporter: @Sciss
Affected Versions: 2.11.0

@scabug
Copy link
Author

scabug commented Aug 5, 2014

@gourlaysama said:
I can't seem to be able to reproduce it...

$ cat test.scala
import scala.tools.nsc.interpreter.IMain

object Test extends App {
  val cl = Thread.currentThread().getContextClassLoader
  println(cl)

  val imain = new IMain()
  imain.interpret("println(42)")
 
  val cl2 = Thread.currentThread().getContextClassLoader
  println(cl2)

  println(cl == cl2)
}
$ scala Test
scala.reflect.internal.util.ScalaClassLoader$URLClassLoader@1f32e575
42
scala.reflect.internal.util.ScalaClassLoader$URLClassLoader@1f32e575
true

@scabug
Copy link
Author

scabug commented May 15, 2015

Martin Grotzke (martin.grotzke) said (edited on May 15, 2015 10:12:49 PM UTC):
I'm also experiencing this with iMain.compile. Before iMain.compile the thread context CL is sun.misc.Launcher$AppClassLoader@368239c8 and afterwards it is scala.reflect.internal.util.ScalaClassLoader$URLClassLoader@39094bde.

This happened in tests (scalatest), where in consequence other tests that try to create an ActorSystem fail because in akka some components are created via reflection relying on the thread context CL:

    sbt.ForkMain$ForkError: interface akka.actor.Scheduler is not assignable from class akka.actor.LightArrayRevolverScheduler
            at akka.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:69)
            at akka.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:66)
            at scala.util.Try$.apply(Try.scala:191)
            at akka.actor.ReflectiveDynamicAccess.getClassFor(DynamicAccess.scala:66)
            at akka.actor.ReflectiveDynamicAccess.createInstanceFor(DynamicAccess.scala:84)
            at akka.actor.ActorSystemImpl.createScheduler(ActorSystem.scala:676)
            at akka.actor.ActorSystemImpl.<init>(ActorSystem.scala:576)
            at akka.actor.ActorSystem$.apply(ActorSystem.scala:142)
            at akka.actor.ActorSystem$.apply(ActorSystem.scala:109)
            at foo.bar.SomeSpec.<init>(SomeSpec.scala:32)
            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
            at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
            at java.lang.Class.newInstance(Class.java:442)
            at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:641)
            at sbt.ForkMain$Run$2.call(ForkMain.java:294)
            at sbt.ForkMain$Run$2.call(ForkMain.java:284)
            at java.util.concurrent.FutureTask.run(FutureTask.java:266)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
            at java.lang.Thread.run(Thread.java:745)

I can reproduce this with this App run from sbt with runMain foo.Main:

package foo

import javax.script.ScriptEngineManager

object Main extends App {

  val ngine = new ScriptEngineManager().getEngineByName("scala")

  val iMain = ngine.asInstanceOf[scala.tools.nsc.interpreter.IMain]
  class Foo
  iMain.settings.embeddedDefaults[Foo]

  println(Thread.currentThread().getContextClassLoader)
  iMain.compile("val x = 1")
  println(Thread.currentThread().getContextClassLoader)

}

scala version is 2.11.6

@scabug
Copy link
Author

scabug commented Jan 23, 2017

@som-snytt said:
scala/scala#5657

@som-snytt
Copy link

https://users.scala-lang.org/t/java-scriptengine-cannot-cast-to-scripted/1166

recaps the reproduction from two years ago.

@som-snytt
Copy link

som-snytt commented Sep 12, 2017

Another mode of suffering

https://gitter.im/scala/scala?at=59b75be4177fb9fe7eacd7f1

https://gist.github.com/cnestor/2c1658d67cf2997a5cc586c7fb0b7fb0

where log4j loads script engines. And then everything breaks.

@adriaanm adriaanm modified the milestones: Backlog, 2.12.4 Sep 21, 2017
@Sciss
Copy link

Sciss commented Dec 15, 2018

I was just bitten by this again in 2.13.0-M5. Thought the issue was solved. I don't really understand this merge. Is it only for Scala 2.12? In the meantime I will reinstall my patch in my IMain subclass like so

      // work-around for SI-8521 (Scala 2.11.0)
      override def interpret(line: String, synthetic: Boolean): Results.Result = {
        val th = Thread.currentThread()
        val cl = th.getContextClassLoader
        try {
          super.interpret(line, synthetic)
        } finally {
          th.setContextClassLoader(cl)
        }
      }

I think the issue should be re-opened and tagged 2.13.x?

@som-snytt
Copy link

@Sciss yes, it was never forward-ported over the scary REPL refactor. I'll refresh my memory and make a PR. One really does take forward-merging for granted.

@lrytz
Copy link
Member

lrytz commented Dec 17, 2018

scala/scala#7544 for 2.13 (scala/scala#5657 for 2.12)

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

No branches or pull requests

5 participants