Better exception handling wrt RMI method invocation
This commit is contained in:
parent
994fa8d196
commit
e621bfb4e3
@ -31,36 +31,25 @@ internal class ListenerManager<CONNECTION: Connection>(private val logger: KLogg
|
|||||||
*/
|
*/
|
||||||
fun cleanStackTrace(throwable: Throwable) {
|
fun cleanStackTrace(throwable: Throwable) {
|
||||||
// NOTE: when we remove stuff, we ONLY want to remove the "tail" of the stacktrace, not ALL parts of the stacktrace
|
// NOTE: when we remove stuff, we ONLY want to remove the "tail" of the stacktrace, not ALL parts of the stacktrace
|
||||||
val reversedList = throwable.stackTrace.reversed().toMutableList()
|
val stackTrace = throwable.stackTrace
|
||||||
|
var newEndIndex = stackTrace.size - 1
|
||||||
// we have to remove kotlin stuff from the stacktrace
|
for (i in newEndIndex downTo 0) {
|
||||||
val reverseIter = reversedList.iterator()
|
val stackName = stackTrace[i].className
|
||||||
while (reverseIter.hasNext()) {
|
if (i == newEndIndex) {
|
||||||
val stackName = reverseIter.next().className
|
if (stackName.startsWith("kotlinx.coroutines.") ||
|
||||||
if (stackName.startsWith("kotlinx.coroutines") || stackName.startsWith("kotlin.coroutines")) {
|
stackName.startsWith("kotlin.coroutines.") ||
|
||||||
// cleanup the stack elements which create the stacktrace
|
stackName.startsWith("dorkbox.network.")) {
|
||||||
reverseIter.remove()
|
newEndIndex--
|
||||||
} else {
|
} else {
|
||||||
// done cleaning up the tail from kotlin
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove dorkbox network stuff
|
|
||||||
while (reverseIter.hasNext()) {
|
|
||||||
val stackName = reverseIter.next().className
|
|
||||||
if (stackName.startsWith("dorkbox.network")) {
|
|
||||||
// cleanup the stack elements which create the stacktrace
|
|
||||||
reverseIter.remove()
|
|
||||||
} else {
|
|
||||||
// done cleaning up the tail from network
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throwable.stackTrace = reversedList.reversed().toTypedArray()
|
// tailToChopIndex will also remove the VERY LAST CachedMethod or CachedAsmMethod access invocation (because it's offset by 1)
|
||||||
|
// NOTE: we want to do this!
|
||||||
|
throwable.stackTrace = stackTrace.copyOfRange(0, newEndIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize a emtpy arrays
|
// initialize a emtpy arrays
|
||||||
|
@ -78,7 +78,6 @@ internal class RmiClient(val isGlobal: Boolean,
|
|||||||
// if we are ASYNC, then this method immediately returns
|
// if we are ASYNC, then this method immediately returns
|
||||||
private suspend fun sendRequest(method: Method, args: Array<Any>): Any? {
|
private suspend fun sendRequest(method: Method, args: Array<Any>): Any? {
|
||||||
|
|
||||||
|
|
||||||
// there is a STRANGE problem, where if we DO NOT respond/reply to method invocation, and immediate invoke multiple methods --
|
// there is a STRANGE problem, where if we DO NOT respond/reply to method invocation, and immediate invoke multiple methods --
|
||||||
// the "server" side can have out-of-order method invocation. There are 2 ways to solve this
|
// the "server" side can have out-of-order method invocation. There are 2 ways to solve this
|
||||||
// 1) make the "server" side single threaded
|
// 1) make the "server" side single threaded
|
||||||
@ -114,6 +113,28 @@ internal class RmiClient(val isGlobal: Boolean,
|
|||||||
throw TimeoutException("Response timed out: ${method.declaringClass.name}.${method.name}")
|
throw TimeoutException("Response timed out: ${method.declaringClass.name}.${method.name}")
|
||||||
}
|
}
|
||||||
is Exception -> {
|
is Exception -> {
|
||||||
|
// reconstruct the stack trace, so the calling method knows where the method invocation happened, and can trace the call
|
||||||
|
// this stack will ALWAYS run up to this method (so we remove from the top->down, to get to the call site)
|
||||||
|
|
||||||
|
val stackTrace = Exception().stackTrace
|
||||||
|
val myClassName = RmiClient::class.java.name
|
||||||
|
|
||||||
|
var newStartIndex = 0
|
||||||
|
for (element in stackTrace) {
|
||||||
|
newStartIndex++
|
||||||
|
|
||||||
|
if (element.className == myClassName && element.methodName == "invoke") {
|
||||||
|
// we do this 1 more time, because we want to remove the proxy invocation off the stack as well.
|
||||||
|
newStartIndex++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val newStack = Array<StackTraceElement>(result.stackTrace.size + stackTrace.size - newStartIndex) { stackTrace[0] }
|
||||||
|
result.stackTrace.copyInto(newStack)
|
||||||
|
stackTrace.copyInto(newStack, result.stackTrace.size, newStartIndex)
|
||||||
|
|
||||||
|
result.stackTrace = newStack
|
||||||
throw result
|
throw result
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@ -252,6 +273,15 @@ internal class RmiClient(val isGlobal: Boolean,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// trampoline so we can access suspend functions correctly and (if suspend) get the coroutine connection parameter)
|
||||||
|
private fun invokeSuspendFunction(continuation: Continuation<*>, suspendFunction: suspend () -> Any?): Any? {
|
||||||
|
return try {
|
||||||
|
SuspendFunctionAccess.invokeSuspendFunction(suspendFunction, continuation)
|
||||||
|
} catch (e: InvocationTargetException) {
|
||||||
|
throw e.cause!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
val prime = 31
|
val prime = 31
|
||||||
var result = 1
|
var result = 1
|
||||||
@ -276,12 +306,4 @@ internal class RmiClient(val isGlobal: Boolean,
|
|||||||
|
|
||||||
return rmiObjectId == other.rmiObjectId
|
return rmiObjectId == other.rmiObjectId
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invokeSuspendFunction(continuation: Continuation<*>, suspendFunction: suspend () -> Any?): Any? {
|
|
||||||
return try {
|
|
||||||
SuspendFunctionAccess.invokeSuspendFunction(suspendFunction, continuation)
|
|
||||||
} catch (e: InvocationTargetException) {
|
|
||||||
throw e.cause!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -358,11 +358,7 @@ internal class RmiSupport(logger: KLogger,
|
|||||||
result.initCause(null)
|
result.initCause(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
// only remove stuff if our logger is NOT on trace (so normal logs will not show extra info, trace will show extra info)
|
|
||||||
if (!logger.isTraceEnabled) {
|
|
||||||
ListenerManager.cleanStackTrace(result as Throwable)
|
ListenerManager.cleanStackTrace(result as Throwable)
|
||||||
}
|
|
||||||
|
|
||||||
logger.error("Error invoking method: ${cachedMethod.method.declaringClass.name}.${cachedMethod.method.name}", result)
|
logger.error("Error invoking method: ${cachedMethod.method.declaringClass.name}.${cachedMethod.method.name}", result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user