in src/jvm/main/org/jetbrains/kotlinx/lincheck/strategy/managed/ManagedStrategy.kt [1886:1926]
override fun onMethodCallException(
threadDescriptor: ThreadDescriptor,
methodId: Int,
receiver: Any?,
params: Array<Any?>,
throwable: Throwable,
interceptor: ResultInterceptor?,
) = threadDescriptor.runInsideIgnoredSection {
val methodDescriptor = context.getMethodDescriptor(methodId)
val deterministicMethodDescriptor = interceptor?.getDeterministicMethodDescriptor()
if (deterministicMethodDescriptor != null) {
deterministicMethodDescriptor.processDeterministicMethodException(receiver, params, throwable, interceptor)
}
val threadId = threadScheduler.getCurrentThreadId()
// check if the called method is an atomics API method
// (e.g., Atomic classes, AFU, VarHandle memory access API, etc.)
val atomicMethodDescriptor = getAtomicMethodDescriptor(receiver, methodDescriptor.methodName)
// get method's analysis section type
val methodSection = methodAnalysisSectionType(
receiver,
methodDescriptor.className,
methodDescriptor.methodName,
atomicMethodDescriptor,
deterministicMethodDescriptor,
)
if (collectTrace && methodSection != AnalysisSectionType.IGNORED) {
// this case is possible and can occur when we resume the coroutine,
// and it results in a call to a top-level actor `suspend` function;
// currently top-level actor functions are not represented in the `callStackTrace`,
// we should probably refactor and fix that, because it is very inconvenient
if (callStackTrace[threadId]!!.isEmpty()) return
val tracePoint = callStackTrace[threadId]!!.last().tracePoint
if (!tracePoint.isActor) tracePoint.initializeThrownException(throwable)
afterMethodCall(threadId, tracePoint)
traceCollector?.addStateRepresentation()
}
// if the method has certain guarantees, leave the corresponding section
leaveAnalysisSection(threadId, methodSection)
}