From ddb48c71c52a7d8d129c9135c34ae86522813830 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 13 Aug 2021 18:48:30 +0300 Subject: [PATCH] Fix BlockHound false-positive in ConflatedChannel Fixes #2866 --- .../src/CoroutinesBlockHoundIntegration.kt | 2 +- .../test/BlockHoundTest.kt | 27 ++++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt b/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt index 190476c41a..8675f32125 100644 --- a/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt +++ b/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt @@ -133,7 +133,7 @@ public class CoroutinesBlockHoundIntegration : BlockHoundIntegration { */ private fun BlockHound.Builder.allowBlockingCallsInConflatedChannel() { for (method in listOf("offerInternal", "offerSelectInternal", "pollInternal", "pollSelectInternal", - "onCancelIdempotent")) + "onCancelIdempotent", "isEmpty", "enqueueReceiveInternal")) { allowBlockingCallsInside("kotlinx.coroutines.channels.ConflatedChannel", method) } diff --git a/kotlinx-coroutines-debug/test/BlockHoundTest.kt b/kotlinx-coroutines-debug/test/BlockHoundTest.kt index 571daca12f..3f58878525 100644 --- a/kotlinx-coroutines-debug/test/BlockHoundTest.kt +++ b/kotlinx-coroutines-debug/test/BlockHoundTest.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.channels.* import org.junit.* import reactor.blockhound.* +@Suppress("UnusedEquals", "DeferredResultUnused", "BlockingMethodInNonBlockingContext") class BlockHoundTest : TestBase() { @Before @@ -12,21 +13,21 @@ class BlockHoundTest : TestBase() { } @Test(expected = BlockingOperationError::class) - fun shouldDetectBlockingInDefault() = runTest { + fun testShouldDetectBlockingInDefault() = runTest { withContext(Dispatchers.Default) { Thread.sleep(1) } } @Test - fun shouldNotDetectBlockingInIO() = runTest { + fun testShouldNotDetectBlockingInIO() = runTest { withContext(Dispatchers.IO) { Thread.sleep(1) } } @Test - fun shouldNotDetectNonblocking() = runTest { + fun testShouldNotDetectNonblocking() = runTest { withContext(Dispatchers.Default) { val a = 1 val b = 2 @@ -54,7 +55,7 @@ class BlockHoundTest : TestBase() { } @Test - fun testChannelsNotBeingConsideredBlocking() = runTest { + fun testChannelNotBeingConsideredBlocking() = runTest { withContext(Dispatchers.Default) { // Copy of kotlinx.coroutines.channels.ArrayChannelTest.testSimple val q = Channel(1) @@ -74,6 +75,24 @@ class BlockHoundTest : TestBase() { } } + @Test + fun testConflatedChannelsNotBeingConsideredBlocking() = runTest { + withContext(Dispatchers.Default) { + val q = Channel(Channel.CONFLATED) + check(q.isEmpty) + check(!q.isClosedForReceive) + check(!q.isClosedForSend) + val sender = launch { + q.send(1) + } + val receiver = launch { + q.receive() == 1 + } + sender.join() + receiver.join() + } + } + @Test(expected = BlockingOperationError::class) fun testReusingThreadsFailure() = runTest { val n = 100