sbt.TrapExitSecurityException thrown at “sbt run”

2020-06-08 03:03发布

问题:

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?

回答1:

// build.sbt
trapExit := false

worked for me



回答2:

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


回答3:

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?



回答4:

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)
    }
  }


回答5:

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.



标签: scala sbt