NOTICK Do not replace stacktrace for local errors (#6635)

We should not overwrite the stack trace of local errors thrown by
`FlowContinuation.Throw` as it hides the real cause of the error.

Exceptions received from peer nodes are still overwritten.
This commit is contained in:
Dan Newton 2020-08-18 12:05:05 +01:00 committed by GitHub
parent abfe83626f
commit 742312b85a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 17 deletions

View File

@ -237,12 +237,11 @@ class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
}
private fun Throwable.fillInLocalStackTrace(): Throwable {
fillInStackTrace()
// provide useful information that can be displayed to the user
// reflection use to access private field
// Fill in the stacktrace when the exception originates from another node
when (this) {
is UnexpectedFlowEndException -> {
DeclaredField<Party?>(UnexpectedFlowEndException::class.java, "peer", this).value?.let {
fillInStackTrace()
stackTrace = arrayOf(
StackTraceElement(
"Received unexpected counter-flow exception from peer ${it.name}",
@ -255,6 +254,7 @@ class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
}
is FlowException -> {
DeclaredField<Party?>(FlowException::class.java, "peer", this).value?.let {
fillInStackTrace()
stackTrace = arrayOf(
StackTraceElement(
"Received counter-flow exception from peer ${it.name}",

View File

@ -389,22 +389,20 @@ class StartedFlowTransition(
}
private fun convertErrorMessageToException(errorMessage: ErrorSessionMessage, peer: Party): Throwable {
val exception: Throwable = if (errorMessage.flowException == null) {
UnexpectedFlowEndException("Counter-flow errored", cause = null, originalErrorId = errorMessage.errorId)
} else {
errorMessage.flowException.originalErrorId = errorMessage.errorId
errorMessage.flowException
}
when (exception) {
// reflection used to access private field
is UnexpectedFlowEndException -> DeclaredField<Party?>(
return if (errorMessage.flowException == null) {
UnexpectedFlowEndException("Counter-flow errored", cause = null, originalErrorId = errorMessage.errorId).apply {
DeclaredField<Party?>(
UnexpectedFlowEndException::class.java,
"peer",
exception
).value = peer
is FlowException -> DeclaredField<Party?>(FlowException::class.java, "peer", exception).value = peer
this
).value = peer
}
} else {
errorMessage.flowException.apply {
originalErrorId = errorMessage.errorId
DeclaredField<Party?>(FlowException::class.java, "peer", errorMessage.flowException).value = peer
}
}
return exception
}
private fun collectUncloseableSessions(sessionIds: Collection<SessionId>, checkpoint: Checkpoint): List<Throwable> {

View File

@ -307,7 +307,7 @@ class FlowFrameworkTests {
.isThrownBy { receivingFiber.resultFuture.getOrThrow() }
.withMessage("Nothing useful")
.withStackTraceContaining(ReceiveFlow::class.java.name) // Make sure the stack trace is that of the receiving flow
.withStackTraceContaining("Received counter-flow exception from peer")
.withStackTraceContaining("Received counter-flow exception from peer ${bob.name}")
bobNode.database.transaction {
assertThat(bobNode.internals.checkpointStorage.checkpoints()).isEmpty()
}
@ -630,6 +630,7 @@ class FlowFrameworkTests {
Notification.createOnNext(ReceiveFlow.START_STEP),
Notification.createOnError(receiveFlowException)
)
assertThat(receiveFlowException).hasStackTraceContaining("Received unexpected counter-flow exception from peer ${bob.name}")
assertSessionTransfers(
aliceNode sent sessionInit(ReceiveFlow::class) to bobNode,