Skip to content

Commit 1cdd471

Browse files
authored
Fix BlockHound false-positive in ConflatedChannel (#2881)
Fixes #2866
1 parent 6055432 commit 1cdd471

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public class CoroutinesBlockHoundIntegration : BlockHoundIntegration {
135135
*/
136136
private fun BlockHound.Builder.allowBlockingCallsInConflatedChannel() {
137137
for (method in listOf("offerInternal", "offerSelectInternal", "pollInternal", "pollSelectInternal",
138-
"onCancelIdempotent"))
138+
"onCancelIdempotent", "isEmpty", "enqueueReceiveInternal"))
139139
{
140140
allowBlockingCallsInside("kotlinx.coroutines.channels.ConflatedChannel", method)
141141
}

kotlinx-coroutines-debug/test/BlockHoundTest.kt

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import kotlinx.coroutines.channels.*
44
import org.junit.*
55
import reactor.blockhound.*
66

7+
@Suppress("UnusedEquals", "DeferredResultUnused", "BlockingMethodInNonBlockingContext")
78
class BlockHoundTest : TestBase() {
89

910
@Before
@@ -12,21 +13,21 @@ class BlockHoundTest : TestBase() {
1213
}
1314

1415
@Test(expected = BlockingOperationError::class)
15-
fun shouldDetectBlockingInDefault() = runTest {
16+
fun testShouldDetectBlockingInDefault() = runTest {
1617
withContext(Dispatchers.Default) {
1718
Thread.sleep(1)
1819
}
1920
}
2021

2122
@Test
22-
fun shouldNotDetectBlockingInIO() = runTest {
23+
fun testShouldNotDetectBlockingInIO() = runTest {
2324
withContext(Dispatchers.IO) {
2425
Thread.sleep(1)
2526
}
2627
}
2728

2829
@Test
29-
fun shouldNotDetectNonblocking() = runTest {
30+
fun testShouldNotDetectNonblocking() = runTest {
3031
withContext(Dispatchers.Default) {
3132
val a = 1
3233
val b = 2
@@ -54,7 +55,7 @@ class BlockHoundTest : TestBase() {
5455
}
5556

5657
@Test
57-
fun testChannelsNotBeingConsideredBlocking() = runTest {
58+
fun testChannelNotBeingConsideredBlocking() = runTest {
5859
withContext(Dispatchers.Default) {
5960
// Copy of kotlinx.coroutines.channels.ArrayChannelTest.testSimple
6061
val q = Channel<Int>(1)
@@ -74,6 +75,24 @@ class BlockHoundTest : TestBase() {
7475
}
7576
}
7677

78+
@Test
79+
fun testConflatedChannelsNotBeingConsideredBlocking() = runTest {
80+
withContext(Dispatchers.Default) {
81+
val q = Channel<Int>(Channel.CONFLATED)
82+
check(q.isEmpty)
83+
check(!q.isClosedForReceive)
84+
check(!q.isClosedForSend)
85+
val sender = launch {
86+
q.send(1)
87+
}
88+
val receiver = launch {
89+
q.receive() == 1
90+
}
91+
sender.join()
92+
receiver.join()
93+
}
94+
}
95+
7796
@Test(expected = BlockingOperationError::class)
7897
fun testReusingThreadsFailure() = runTest {
7998
val n = 100

0 commit comments

Comments
 (0)