[K/N] Refactor unhandled exception handling API
* Do not reset unhandled exception hook * Add processUnhandledException to perform default unhandled exception processing * Add terminateWithUnhandledException to report the unhandled exception and terminate the program * Use the default unhandled exception processing in entrypoint, interop boundaries and in Worker.executeAfter * Add -Xworker-exception-handling to control exception processing of Worker.executeAfter. By default its the old behaviour with the old MM, and new behaviour with the new MM.
This commit is contained in:
committed by
Space
parent
766857881a
commit
7e04bb4bf1
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
@file:OptIn(ExperimentalStdlibApi::class)
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
fun main() {
|
||||
val exceptionHook = { _: Throwable ->
|
||||
println("Hook")
|
||||
}.freeze()
|
||||
|
||||
val oldHook = setUnhandledExceptionHook(exceptionHook)
|
||||
assertNull(oldHook)
|
||||
val hook1 = getUnhandledExceptionHook()
|
||||
assertEquals(exceptionHook, hook1)
|
||||
val hook2 = getUnhandledExceptionHook()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
data class C(val x: Int)
|
||||
|
||||
fun main() {
|
||||
Platform.isMemoryLeakCheckerActive = true
|
||||
|
||||
val c = C(42)
|
||||
setUnhandledExceptionHook({ _: Throwable ->
|
||||
println("Hook ${c.x}")
|
||||
}.freeze())
|
||||
|
||||
throw Error("an error")
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
@file:OptIn(ExperimentalStdlibApi::class)
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
fun customExceptionHook(throwable: Throwable) {
|
||||
println("Hook called")
|
||||
assertEquals(::customExceptionHook, getUnhandledExceptionHook())
|
||||
}
|
||||
|
||||
fun main() {
|
||||
setUnhandledExceptionHook((::customExceptionHook).freeze())
|
||||
|
||||
throw Error("some error")
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
@file:OptIn(ExperimentalStdlibApi::class)
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
fun main() {
|
||||
setUnhandledExceptionHook({ t: Throwable ->
|
||||
println("Hook called")
|
||||
terminateWithUnhandledException(t)
|
||||
}.freeze())
|
||||
|
||||
throw Error("some error")
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
@file:OptIn(ExperimentalStdlibApi::class)
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
fun main() {
|
||||
setUnhandledExceptionHook({ t: Throwable ->
|
||||
println("Hook called")
|
||||
terminateWithUnhandledException(t)
|
||||
}.freeze())
|
||||
|
||||
val exception = Error("some error")
|
||||
processUnhandledException(exception)
|
||||
println("Not going to happen")
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
fun customExceptionHook(throwable: Throwable) {
|
||||
println("Hook called")
|
||||
throw Error("another error")
|
||||
}
|
||||
|
||||
fun main() {
|
||||
setUnhandledExceptionHook((::customExceptionHook).freeze())
|
||||
|
||||
throw Error("some error")
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
@file:OptIn(ExperimentalStdlibApi::class)
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
fun main() {
|
||||
val called = AtomicInt(0)
|
||||
setUnhandledExceptionHook({ _: Throwable ->
|
||||
called.value = 1
|
||||
}.freeze())
|
||||
|
||||
val exception = Error("some error")
|
||||
processUnhandledException(exception)
|
||||
assertEquals(1, called.value)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
@file:OptIn(ExperimentalStdlibApi::class)
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
fun main() {
|
||||
val exception = Error("some error")
|
||||
terminateWithUnhandledException(exception)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
@file:OptIn(ExperimentalStdlibApi::class)
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
fun main() {
|
||||
val exception = Error("some error")
|
||||
processUnhandledException(exception)
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package runtime.workers.worker_exceptions
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
@Test
|
||||
fun testExecuteAfterStartQuiet() {
|
||||
val worker = Worker.start(errorReporting = false)
|
||||
worker.executeAfter(0L, {
|
||||
throw Error("testExecuteAfterStartQuiet error")
|
||||
}.freeze())
|
||||
worker.requestTermination().result
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExecuteStart() {
|
||||
val worker = Worker.start()
|
||||
val future = worker.execute(TransferMode.SAFE, {}) {
|
||||
throw Error("testExecuteStart error")
|
||||
}
|
||||
assertFailsWith<Throwable> {
|
||||
future.result
|
||||
}
|
||||
worker.requestTermination().result
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExecuteStartQuiet() {
|
||||
val worker = Worker.start(errorReporting = false)
|
||||
val future = worker.execute(TransferMode.SAFE, {}) {
|
||||
throw Error("testExecuteStartQuiet error")
|
||||
}
|
||||
assertFailsWith<Throwable> {
|
||||
future.result
|
||||
}
|
||||
worker.requestTermination().result
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package runtime.workers.worker_exceptions_legacy
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
@Test
|
||||
fun testExecuteAfterStartLegacy() {
|
||||
val worker = Worker.start()
|
||||
worker.executeAfter(0L, {
|
||||
throw Error("testExecuteAfterStartLegacy error")
|
||||
}.freeze())
|
||||
worker.requestTermination().result
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExecuteStartLegacy() {
|
||||
val worker = Worker.start()
|
||||
val future = worker.execute(TransferMode.SAFE, {}) {
|
||||
throw Error("testExecuteStartLegacy error")
|
||||
}
|
||||
assertFailsWith<Throwable> {
|
||||
future.result
|
||||
}
|
||||
worker.requestTermination().result
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
fun main() {
|
||||
val worker = Worker.start()
|
||||
worker.executeAfter(0L, {
|
||||
throw Error("some error")
|
||||
}.freeze())
|
||||
worker.requestTermination().result
|
||||
println("Will not happen")
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
fun main() {
|
||||
Worker.current.executeAfter(0L, {
|
||||
throw Error("some error")
|
||||
}.freeze())
|
||||
Worker.current.processQueue()
|
||||
println("Will not happen")
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
fun main() {
|
||||
setUnhandledExceptionHook({ _: Throwable ->
|
||||
println("hook called")
|
||||
}.freeze())
|
||||
|
||||
|
||||
val worker = Worker.start()
|
||||
worker.executeAfter(0L, {
|
||||
throw Error("some error")
|
||||
}.freeze())
|
||||
worker.requestTermination().result
|
||||
println("Will happen")
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
fun main() {
|
||||
setUnhandledExceptionHook({ _: Throwable ->
|
||||
println("hook called")
|
||||
}.freeze())
|
||||
|
||||
Worker.current.executeAfter(0L, {
|
||||
throw Error("some error")
|
||||
}.freeze())
|
||||
Worker.current.processQueue()
|
||||
println("Will happen")
|
||||
}
|
||||
Reference in New Issue
Block a user