sandbox: On initialization error, actually print the error and stop. (#4239)

Three problems here:

1. On failure, the Sandbox didn't close down the metrics reporting
thread, meaning the application would hang.
2. If there's a failure:
  a. we didn't print it, and
  b. we didn't exit with the correct status code.

These are now handled.

CHANGELOG_BEGIN
- [Sandbox] On initialization error, report the error correctly and exit
  with a status code of 1. Previously, the program would hang
  indefinitely. (This regression was introduced in v0.13.41.)
CHANGELOG_END

Co-authored-by: Samir Talwar <samir.talwar@digitalasset.com>
This commit is contained in:
Samir Talwar 2020-01-28 13:25:29 +01:00 committed by mergify[bot]
parent 74984559e8
commit ebfb0c4a97
2 changed files with 26 additions and 6 deletions

View File

@ -26,12 +26,19 @@ object SandboxMain extends App {
if (closed.compareAndSet(false, true)) server.close()
}
server.failure.foreach { exception =>
logger.error(
s"Shutting down Sandbox application due to an initialization error:\n${exception.getMessage}")
sys.exit(1)
}
try {
Runtime.getRuntime.addShutdownHook(new Thread(() => closeServer()))
} catch {
case NonFatal(t) =>
logger.error("Shutting down Sandbox application because of initialization error", t)
case NonFatal(exception) =>
logger.error("Shutting down Sandbox application due to an initialization error.", exception)
closeServer()
sys.exit(1)
}
}

View File

@ -113,12 +113,26 @@ final class SandboxServer(config: => SandboxConfig) extends AutoCloseable {
private val authService: AuthService = config.authService.getOrElse(AuthServiceWildcard)
private val metrics = new MetricRegistry
private val metricsReporting =
new MetricsReporting(metrics, "com.digitalasset.platform.sandbox")
@volatile private var sandboxState: Resource[SandboxState] = _
sandboxState = start()(DirectExecutionContext)
sandboxState = {
implicit val executionContext: ExecutionContext = DirectExecutionContext
for {
_ <- ResourceOwner
.forCloseable(() => new MetricsReporting(metrics, getClass.getPackage.getName))
.acquire()
state <- start()
} yield state
}
def failure: Option[Throwable] =
Await
.result(
sandboxState.asFuture.transformWith(Future.successful)(DirectExecutionContext),
AsyncTolerance)
.failed
.toOption
def port: Int =
Await.result(portF(DirectExecutionContext), AsyncTolerance)
@ -307,7 +321,6 @@ final class SandboxServer(config: => SandboxConfig) extends AutoCloseable {
}
override def close(): Unit = {
metricsReporting.close()
Await.result(
sandboxState.flatMap(_.apiServer)(DirectExecutionContext).release(),
AsyncTolerance)