I've created a simple Scala console application. I run it by sbt run
and always receive the following exception on exit:
Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-0"
[success] Total time: 17 s, completed 30.01.2014 22:19:37
After that all my console output becomes invisible. I can type and run applications but I cannot see what I'm typing.
What does this exception means? What am I doing wrong?
// build.sbt
trapExit := false
worked for me
You can fork your JVM when running a console application within an SBT session. That way when your console application exits it won't kill the hosting sbt JVM. I'm doing this for main
classes in my integration test configuration.
In build.sbt
(or your equivalent sbt project configuration file):
fork in (IntegrationTest, run) := true
(you may want simply fork in run := true
to cover a console main). Then in any class that extends App
:
package com.example
object StuffMain extends App {
println("stuff")
sys.exit(0) // 0 is a successful Unix exit code
}
(You may not need a sys.exit
call at all, if your application doesn't keep the forked JVM alive.)
In my case I can then execute this integration test StuffMain
by running:
sbt> it:runMain com.example.StuffMain
It's not clear what SBT version you use, but with SBT 0.13.2-M1 it was quite easily reproduced with the following class:
Hello.scala
object ExitApp extends App {
exit(0)
}
The class exactly shows when the exception sbt.TrapExitSecurityException
gets thrown - whenever the method java.lang.Runtime.exit(int) is called.
$ sbt run
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Loading project definition from /Users/jacek/sandbox/so/TrapExitSecurityException/project
[info] Set current project to trapexitsecurityexception (in build file:/Users/jacek/sandbox/so/TrapExitSecurityException/)
[warn] there were 1 deprecation warning(s); re-run with -deprecation for details
[warn] one warning found
[info] Running ExitApp
Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-0"
[success] Total time: 6 s, completed Jan 30, 2014 9:05:24 PM
Remove the call from your application and the exception goes away. According to sbt.TrapExit
scaladoc:
This category of code should only be called by forking a new JVM.
Why do you use it at all?
This exception is not a bug.
SBT is simply warning you that the running application called sys.exit(0)
. Instead of terminate the JVM (and killing SBT on the same occasion), SBT intercepts that call and keep the JVM running, so you can continue to interact with SBT.
I found this explanation by inspecting the source code of SBT:
/** SecurityManager hook to trap calls to `System.exit` to avoid shutting down the whole JVM.*/
override def checkExit(status: Int): Unit = if (active) {
val t = currentThread
val stack = t.getStackTrace
if (stack == null || stack.exists(isRealExit)) {
exitApp(t, status)
throw new TrapExitSecurityException(status)
}
}
I don't know if this is what the OP had but I ran into the same error message and wanted to share my solution for others to find. I'm using Guice for dependency injection and had found myself in a circular dependency situation. This was causing my application to barf when it was trying to set everything up and create all my singletons to inject.
A little more in case that wasn't clear enough.
- SingletonA injects SingletonB
- SingletonB injects SingletonC
- SingletonC injects SingletonA <-- barf because SingletonA hasn't finished being instantiated yet.
I hope that helps someone find a solution quicker. My circle had 3 singletons involved, as illustrated above, so it took me longer to realize.