Skip to content

Commit

Permalink
Fix BlockHound false positives related to use of ServiceLoader
Browse files Browse the repository at this point in the history
Fixes #2190
  • Loading branch information
dkhalanskyjb committed Oct 23, 2020
1 parent d69bf24 commit b6eb7a0
Showing 1 changed file with 14 additions and 3 deletions.
17 changes: 14 additions & 3 deletions kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt
Expand Up @@ -10,8 +10,7 @@ import reactor.blockhound.integration.*
public class CoroutinesBlockHoundIntegration : BlockHoundIntegration {

override fun applyTo(builder: BlockHound.Builder): Unit = with(builder) {
allowBlockingCallsInside("kotlinx.coroutines.channels.AbstractSendChannel", "sendSuspend")
// these classes use a lock internally
// These classes use a lock internally, but should be safe to use.
for (method in listOf(
"pollInternal", "isEmpty", "isFull", "isClosedForReceive", "offerInternal", "offerSelectInternal",
"enqueueSend", "pollInternal", "pollSelectInternal", "enqueueReceiveInternal", "onCancelIdempotent" ))
Expand All @@ -29,8 +28,20 @@ public class CoroutinesBlockHoundIntegration : BlockHoundIntegration {
{
allowBlockingCallsInside("kotlinx.coroutines.channels.ConflatedChannel", method)
}
// should be safe; used for sending tasks to a thread pool
allowBlockingCallsInside("kotlinx.coroutines.channels.AbstractSendChannel", "sendSuspend")
/* This method may block as part of its implementation, but is probably safe. We need to whitelist it so that
it is possible to enqueue coroutines in contexts that use thread pools from other coroutines in a way that's not
considered blocking. */
allowBlockingCallsInside("java.util.concurrent.ScheduledThreadPoolExecutor", "execute")
/* These files have fields that invoke service loaders. They are manually whitelisted; another approach could be
to whitelist the operations performed by service loaders, as they can generally be considered safe. This was not
done here because ServiceLoader has a large API surface, with some methods being hidden as implementation
details (in particular, the implementation of its iterator is completely opaque). Relying on particular names
being used in ServiceLoader's implementation would be brittle. */
allowBlockingCallsInside("kotlinx.coroutines.reactive.ReactiveFlowKt", "<clinit>")
allowBlockingCallsInside("kotlinx.coroutines.CoroutineExceptionHandlerImplKt", "<clinit>")
/* The predicates that define that BlockHound should only report blocking calls from threads that are part of
the coroutine thread pool and currently execute a CPU-bound coroutine computation. */
addDynamicThreadPredicate { isSchedulerWorker(it) }
nonBlockingThreadPredicate { p -> p.or { mayNotBlock(it) } }
}
Expand Down

0 comments on commit b6eb7a0

Please sign in to comment.