Skip to content

Commit e60bcbd

Browse files
authored
Fix hanging RunInterruptibleStressTest on Windows with JDK 1.6 (Kotlin#2145)
The test is improved so that it fails, not hangs, on a failure. However, it will not pass on Windows + JDK 1.6 due to a bug in JDK (which can be easily confirmed with this modification to a test), so it excluded when running on JDK 1.6. Fixes Kotlin#2144
1 parent d55d8e8 commit e60bcbd

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

kotlinx-coroutines-core/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ task jdk16Test(type: Test, dependsOn: [compileTestKotlinJvm, checkJdk16]) {
131131
exclude '**/*LCStressTest.*' // lin-check tests use LinChecker which needs JDK8
132132
exclude '**/exceptions/**' // exceptions tests check suppressed exception which needs JDK8
133133
exclude '**/ExceptionsGuideTest.*'
134+
exclude '**/RunInterruptibleStressTest.*' // fails on JDK 1.6 due to JDK bug
134135
}
135136

136137
// Run these tests only during nightly stress test

kotlinx-coroutines-core/jvm/test/RunInterruptibleStressTest.kt

+13-11
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,29 @@ import org.junit.Test
99
import java.util.concurrent.atomic.*
1010
import kotlin.test.*
1111

12+
/**
13+
* Stress test for [runInterruptible].
14+
* It does not pass on JDK 1.6 on Windows: [Thread.sleep] times out without being interrupted despite the
15+
* fact that thread interruption flag is set.
16+
*/
1217
class RunInterruptibleStressTest : TestBase() {
13-
1418
@get:Rule
1519
val dispatcher = ExecutorRule(4)
16-
private val REPEAT_TIMES = 1000 * stressTestMultiplier
20+
private val repeatTimes = 1000 * stressTestMultiplier
1721

1822
@Test
19-
fun testStress() = runBlocking {
20-
val interruptLeak = AtomicBoolean(false)
23+
fun testStress() = runTest {
2124
val enterCount = AtomicInteger(0)
2225
val interruptedCount = AtomicInteger(0)
2326

24-
repeat(REPEAT_TIMES) {
27+
repeat(repeatTimes) {
2528
val job = launch(dispatcher) {
2629
try {
2730
runInterruptible {
2831
enterCount.incrementAndGet()
2932
try {
30-
Thread.sleep(Long.MAX_VALUE)
33+
Thread.sleep(10_000)
34+
error("Sleep was not interrupted, Thread.isInterrupted=${Thread.currentThread().isInterrupted}")
3135
} catch (e: InterruptedException) {
3236
interruptedCount.incrementAndGet()
3337
throw e
@@ -36,19 +40,17 @@ class RunInterruptibleStressTest : TestBase() {
3640
} catch (e: CancellationException) {
3741
// Expected
3842
} finally {
39-
interruptLeak.set(interruptLeak.get() || Thread.currentThread().isInterrupted)
43+
assertFalse(Thread.currentThread().isInterrupted, "Interrupt flag should not leak")
4044
}
4145
}
4246
// Add dispatch delay
4347
val cancelJob = launch(dispatcher) {
4448
job.cancel()
4549
}
46-
47-
job.start()
4850
joinAll(job, cancelJob)
4951
}
50-
51-
assertFalse(interruptLeak.get())
52+
println("Entered runInterruptible ${enterCount.get()} times")
53+
assertTrue(enterCount.get() > 0) // ensure timing is Ok and we don't cancel it all prematurely
5254
assertEquals(enterCount.get(), interruptedCount.get())
5355
}
5456
}

0 commit comments

Comments
 (0)