From bcc46577aab9845fd16df3db1458eddd447c57c0 Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 19 Aug 2020 15:06:10 +0200 Subject: [PATCH] Added more stack cleanup methods --- .../network/connection/ListenerManager.kt | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/dorkbox/network/connection/ListenerManager.kt b/src/dorkbox/network/connection/ListenerManager.kt index 61d40660..9e8ed2d1 100644 --- a/src/dorkbox/network/connection/ListenerManager.kt +++ b/src/dorkbox/network/connection/ListenerManager.kt @@ -24,12 +24,44 @@ internal class ListenerManager(private val logger: KLogg val LOAD_FACTOR = 0.8f + /** + * Remove from the stacktrace until we get to the invoke site (ie: remove kotlin coroutine info + dorkbox network call stack) + * + * Neither of these are useful in resolving exception handling from a users perspective, and only clutter the stacktrace. + */ + fun cleanStackTrace(localThrowable: Throwable, invokingClass: Class<*>, remoteException: Exception? = null) { + val myClassName = invokingClass.name + val stackTrace = localThrowable.stackTrace + 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 + } + } + + if (remoteException == null) { + // no remote exception, just cleanup our own callstack + localThrowable.stackTrace = stackTrace.copyOfRange(newStartIndex, stackTrace.size) + } else { + // merge this info into the remote exception, so we can get the correct call stack info + val newStack = Array(remoteException.stackTrace.size + stackTrace.size - newStartIndex) { stackTrace[0] } + remoteException.stackTrace.copyInto(newStack) + stackTrace.copyInto(newStack, remoteException.stackTrace.size, newStartIndex) + + remoteException.stackTrace = newStack + } + } + /** * Remove from the stacktrace (going in reverse), kotlin coroutine info + dorkbox network call stack. * * Neither of these are useful in resolving exception handling from a users perspective, and only clutter the stacktrace. */ - fun cleanStackTrace(throwable: Throwable) { + fun cleanStackTraceReverse(throwable: Throwable) { // NOTE: when we remove stuff, we ONLY want to remove the "tail" of the stacktrace, not ALL parts of the stacktrace val stackTrace = throwable.stackTrace var newEndIndex = Math.max(0, stackTrace.size - 1) @@ -48,8 +80,7 @@ internal class ListenerManager(private val logger: KLogg } } - // tailToChopIndex will also remove the VERY LAST CachedMethod or CachedAsmMethod access invocation (because it's offset by 1) - // NOTE: we want to do this! + // newEndIndex will also remove the VERY LAST CachedMethod or CachedAsmMethod access invocation (because it's offset by 1) throwable.stackTrace = stackTrace.copyOfRange(0, newEndIndex) } } @@ -301,7 +332,7 @@ internal class ListenerManager(private val logger: KLogg it(connection) } catch (t: Throwable) { // NOTE: when we remove stuff, we ONLY want to remove the "tail" of the stacktrace, not ALL parts of the stacktrace - cleanStackTrace(t) + cleanStackTraceReverse(t) notifyError(connection, t) } } @@ -316,7 +347,7 @@ internal class ListenerManager(private val logger: KLogg it(connection) } catch (t: Throwable) { // NOTE: when we remove stuff, we ONLY want to remove the "tail" of the stacktrace, not ALL parts of the stacktrace - cleanStackTrace(t) + cleanStackTraceReverse(t) notifyError(connection, t) } }