BlockHound false positive in kotlin.jvm.internal.Reflection.renderLambdaToString
OliverO2 opened this issue · 3 comments
kotlinx-coroutines-debug:1.8.0
This one appeared once when running Kotest in debug mode with env KOTEST_DEBUG=true ./gradlew ...
:
reactor.blockhound.BlockingOperationError: Blocking call! jdk.internal.misc.Unsafe#park
at app//io.kotest.extensions.blockhound.KotestBlockHoundIntegration.applyTo$lambda$2$lambda$1(KotestBlockHoundIntegration.kt:28)
at app//reactor.blockhound.BlockHound$Builder.lambda$install$8(BlockHound.java:488)
at reactor.blockhound.BlockHoundRuntime.checkBlocking(BlockHoundRuntime.java:89)
at java.base@17.0.10/jdk.internal.misc.Unsafe.park(Unsafe.java)
at java.base@17.0.10/java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at java.base@17.0.10/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:715)
at java.base@17.0.10/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:938)
at java.base@17.0.10/java.util.concurrent.locks.ReentrantLock$Sync.lock(ReentrantLock.java:153)
at java.base@17.0.10/java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:322)
at app//kotlin.reflect.jvm.internal.impl.storage.DefaultSimpleLock.lock(locks.kt:48)
at app//kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:554)
at app//kotlin.reflect.jvm.internal.impl.serialization.deserialization.TypeDeserializer.typeConstructor(TypeDeserializer.kt:156)
at app//kotlin.reflect.jvm.internal.impl.serialization.deserialization.TypeDeserializer.simpleType(TypeDeserializer.kt:91)
at app//kotlin.reflect.jvm.internal.impl.serialization.deserialization.TypeDeserializer.type(TypeDeserializer.kt:68)
at app//kotlin.reflect.jvm.internal.impl.serialization.deserialization.MemberDeserializer.loadFunction(MemberDeserializer.kt:218)
at app//kotlin.reflect.jvm.ReflectLambdaKt$reflect$descriptor$1.invoke(reflectLambda.kt:46)
at app//kotlin.reflect.jvm.ReflectLambdaKt$reflect$descriptor$1.invoke(reflectLambda.kt:46)
at app//kotlin.reflect.jvm.internal.UtilKt.deserializeToDescriptor(util.kt:267)
at app//kotlin.reflect.jvm.ReflectLambdaKt.reflect(reflectLambda.kt:45)
at app//kotlin.reflect.jvm.internal.ReflectionFactoryImpl.renderLambdaToString(ReflectionFactoryImpl.java:56)
at app//kotlin.reflect.jvm.internal.ReflectionFactoryImpl.renderLambdaToString(ReflectionFactoryImpl.java:51)
at app//kotlin.jvm.internal.Reflection.renderLambdaToString(Reflection.java:79)
at app//kotlin.jvm.internal.Lambda.toString(Lambda.kt:11)
at java.base@17.0.10/java.lang.String.valueOf(String.java:4220)
at java.base@17.0.10/java.lang.StringBuilder.append(StringBuilder.java:173)
at app//io.kotest.core.test.config.ResolvedTestConfig.toString(ResolvedTestConfig.kt)
at java.base@17.0.10/java.lang.String.valueOf(String.java:4220)
at java.base@17.0.10/java.lang.StringBuilder.append(StringBuilder.java:173)
at app//io.kotest.core.test.TestCase.toString(TestCase.kt)
at java.base@17.0.10/java.lang.String.valueOf(String.java:4220)
at java.base@17.0.10/java.lang.StringBuilder.append(StringBuilder.java:173)
at app//io.kotest.core.test.TestCase.toString(TestCase.kt)
at java.base@17.0.10/java.lang.String.valueOf(String.java:4220)
at java.base@17.0.10/java.lang.StringBuilder.append(StringBuilder.java:173)
at app//io.kotest.engine.test.listener.TestCaseExecutionListenerToTestEngineListenerAdapter$testFinished$2.invoke(TestCaseExecutionListenerToTestEngineListenerAdapter.kt:19)
at app//io.kotest.engine.test.listener.TestCaseExecutionListenerToTestEngineListenerAdapter$testFinished$2.invoke(TestCaseExecutionListenerToTestEngineListenerAdapter.kt:19)
at app//io.kotest.mpp.Logger$log$1.invoke(logger.kt:19)
at app//io.kotest.mpp.Logger$log$1.invoke(logger.kt:18)
at app//io.kotest.mpp.LoggerKt.log(logger.kt:41)
at app//io.kotest.mpp.Logger.log(logger.kt:18)
at app//io.kotest.engine.test.listener.TestCaseExecutionListenerToTestEngineListenerAdapter.testFinished(TestCaseExecutionListenerToTestEngineListenerAdapter.kt:19)
at app//io.kotest.engine.test.interceptors.TestFinishedInterceptor.intercept(TestFinishedInterceptor.kt:26)
at app//io.kotest.engine.test.interceptors.TestFinishedInterceptor$intercept$1.invokeSuspend(TestFinishedInterceptor.kt)
at app//kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at app//kotlinx.coroutines.internal.ScopeCoroutine.afterResume(Scopes.kt:28)
at app//kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:99)
at app//kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at app//kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at app//kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:585)
at app//kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:802)
at app//kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:706)
at app//kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:693)
Might be worth adding an allowance to BlockHound.Builder.allowBlockingCallsInReflectionImpl()
at whatever level is deemed appropriate.
The error complains about our reflect library and we (coroutines) are unlikely to ship BH rules for anything but coroutines themselves.
Would it work for you to add a rule in your project for the whole Kotlin reflect package?
On a side note, the fact that renderToString
acquires a global lock is issue on its own, but alas it's more complicated then "just fix it"
we (coroutines) are unlikely to ship BH rules for anything but coroutines themselves.
We already do:
for the whole Kotlin reflect package?
A bit scary, given that reflection can execute arbitrary user-supplied code.
The error complains about our reflect library and we (coroutines) are unlikely to ship BH rules for anything but coroutines themselves.
Surely a balancing issue, just thought to let you know because some reflection allowance was already there.
Would it work for you to add a rule in your project for the whole Kotlin reflect package?
Sure, no big deal. [Edit: Not the whole package, but selected reflection functions.]
On a side note, the fact that renderToString acquires a global lock is issue on its own, but alas it's more complicated then "just fix it"
Agreed.