sbt.TrapExitSecurityException抛出"sbt run"

Ily*_*nev 17 scala sbt

我已经创建了一个简单的Scala控制台应用程序.我运行它sbt run并在退出时始终收到以下异常:

Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-0"
[success] Total time: 17 s, completed 30.01.2014 22:19:37
Run Code Online (Sandbox Code Playgroud)

之后我的所有控制台输出都变得不可见.我可以输入和运行应用程序,但我看不到我在键入的内容.

这个例外是什么意思?我究竟做错了什么?

Dan*_*hin 13

// build.sbt
trapExit := false
Run Code Online (Sandbox Code Playgroud)

为我工作


cfe*_*uke 10

在SBT会话中运行控制台应用程序时,可以派生JVM.这样,当您的控制台应用程序退出时,它不会杀死托管的sbt JVM.我正在为main集成测试配置中的类做这个.

build.sbt(或等效的sbt项目配置文件中):

fork in (IntegrationTest, run) := true
Run Code Online (Sandbox Code Playgroud)

(您可能只想fork in run := true覆盖控制台主机).然后在任何扩展的类App:

package com.example

object StuffMain extends App {
  println("stuff")

  sys.exit(0) // 0 is a successful Unix exit code
}
Run Code Online (Sandbox Code Playgroud)

(sys.exit如果您的应用程序没有使分叉的JVM保持活动状态,则可能根本不需要调用.)

在我的情况下,我可以StuffMain通过运行执行此集成测试:

sbt> it:runMain com.example.StuffMain
Run Code Online (Sandbox Code Playgroud)


Jac*_*ski 6

目前尚不清楚您使用的是什么SBT版本,但使用SBT 0.13.2-M1时,可以通过以下类轻松复制:

Hello.scala

object ExitApp extends App {
  exit(0)
}
Run Code Online (Sandbox Code Playgroud)

该类确切地显示何时sbt.TrapExitSecurityException抛出异常 - 每当调用方法java.lang.Runtime.exit(int)时.

$ 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
Run Code Online (Sandbox Code Playgroud)

从您的应用程序中删除该调用,该异常消失.根据sbt.TrapExitscaladoc:

只应通过分支新的JVM来调用此类代码.

你为什么一直使用它?

  • 正确的终止方法就是让主线程返回.此外,这看起来像Jline"重置终端"的错误.请在sbt上打开一个问题,因为你应该恢复控制台.我们的安全管理器旨在允许代码中的sys.exit(0)而不是死得很厉害. (2认同)
  • 在许多情况下,您希望退出控制台应用程序而不是0,如`System.exit(1)`.这显然是为什么. (2认同)

Zen*_*ulz 6

此异常不是错误。

SBT 只是警告您正在运行的应用程序调用了sys.exit(0). SBT 不会终止 JVM(并在同一场合终止 SBT),而是会拦截该调用并保持 JVM 运行,以便您可以继续与 SBT 交互。

我通过检查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)
    }
  }
Run Code Online (Sandbox Code Playgroud)