Properly close a number of classloaders

I discovered there were a number of places where closing a ClassLoader
didn't work correctly because I was assuming it was a URLClassLoader
when it was actually a ClasspathFilter. I also incorrectly imported the
wrong kind of URLClassLoader in Run.scala. Finally, I close the
SbtMetaBuildClassLoader when xMain exits now.
This commit is contained in:
Ethan Atkins 2019-05-02 14:01:17 -07:00
parent bc21db2864
commit 67df72ab01
4 changed files with 26 additions and 10 deletions

View File

@ -29,6 +29,7 @@ import sbt.Scope.{ GlobalScope, ThisScope, fillTaskAxis }
import sbt.internal.CommandStrings.ExportStream
import sbt.internal._
import sbt.internal.inc.JavaInterfaceUtil._
import sbt.internal.inc.classpath.ClasspathFilter
import sbt.internal.inc.{ ZincLmUtil, ZincUtil }
import sbt.internal.io.{ Source, WatchState }
import sbt.internal.librarymanagement.{ CustomHttp => _, _ }
@ -795,13 +796,17 @@ object Defaults extends BuildCommon {
// ((streams in test, loadedTestFrameworks, testLoader, testGrouping in test, testExecution in test, fullClasspath in test, javaHome in test, testForkedParallel, javaOptions in test) flatMap allTestGroupsTask).value,
testResultLogger in (Test, test) :== TestResultLogger.SilentWhenNoTests, // https://github.com/sbt/sbt/issues/1185
test := {
val loader = testLoader.value match { case u: URLClassLoader => Some(u); case _ => None }
val close = testLoader.value match {
case u: URLClassLoader => Some(() => u.close())
case c: ClasspathFilter => Some(() => c.close())
case _ => None
}
val trl = (testResultLogger in (Test, test)).value
val taskName = Project.showContextKey(state.value).show(resolvedScoped.value)
try {
trl.run(streams.value.log, executeTests.value, taskName)
} finally {
loader.foreach(_.close())
close.foreach(_.apply())
}
},
testOnly := inputTests(testOnly).evaluated,

View File

@ -50,6 +50,11 @@ final class xMain extends xsbti.AppMain {
case e: InvocationTargetException =>
// This propogates xsbti.FullReload to the launcher
throw e.getCause
} finally {
loader match {
case a: AutoCloseable => a.close()
case _ =>
}
}
}
/*

View File

@ -226,6 +226,11 @@ private[sbt] object SbtMetaBuildClassLoader {
}
new URLClassLoader(rest, updatedLibraryLoader) {
override def toString: String = s"SbtMetaBuildClassLoader"
override def close(): Unit = {
super.close()
updatedLibraryLoader.close()
interfaceLoader.close()
}
}
}
}

View File

@ -8,19 +8,19 @@
package sbt
import java.io.File
import java.lang.reflect.{ Method, Modifier }
import Modifier.{ isPublic, isStatic }
import java.lang.reflect.Method
import java.lang.reflect.Modifier.{ isPublic, isStatic }
import java.net.URLClassLoader
import sbt.internal.inc.classpath.ClasspathUtilities
import sbt.internal.inc.ScalaInstance
import sbt.internal.inc.classpath.{ ClasspathFilter, ClasspathUtilities }
import sbt.internal.util.MessageOnlyException
import sbt.io.Path
import sbt.util.Logger
import scala.reflect.internal.util.ScalaClassLoader.URLClassLoader
import scala.util.{ Failure, Success, Try }
import scala.util.control.NonFatal
import scala.sys.process.Process
import scala.util.control.NonFatal
import scala.util.{ Failure, Success, Try }
sealed trait ScalaRun {
def run(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger): Try[Unit]
@ -98,8 +98,9 @@ class Run(newLoader: Seq[File] => ClassLoader, trapExit: Boolean) extends ScalaR
invokeMain(loader, main, options)
} finally {
loader match {
case u: URLClassLoader => u.close()
case _ =>
case u: URLClassLoader => u.close()
case c: ClasspathFilter => c.close()
case _ =>
}
}
}