From 92685f525a6e0a854e4d2f80845e37b32e2845b1 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Fri, 17 Jul 2020 11:41:38 +0300 Subject: [PATCH] Fix hanging RunInterruptibleStressTest on Windows with JDK 1.6 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 #2144 --- kotlinx-coroutines-core/build.gradle | 1 + .../jvm/test/RunInterruptibleStressTest.kt | 24 ++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index be7622aa49..59dc5da894 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -131,6 +131,7 @@ task jdk16Test(type: Test, dependsOn: [compileTestKotlinJvm, checkJdk16]) { exclude '**/*LCStressTest.*' // lin-check tests use LinChecker which needs JDK8 exclude '**/exceptions/**' // exceptions tests check suppressed exception which needs JDK8 exclude '**/ExceptionsGuideTest.*' + exclude '**/RunInterruptibleStressTest.*' // fails on JDK 1.6 due to JDK bug } // Run these tests only during nightly stress test diff --git a/kotlinx-coroutines-core/jvm/test/RunInterruptibleStressTest.kt b/kotlinx-coroutines-core/jvm/test/RunInterruptibleStressTest.kt index 79251bb3b8..701b958afd 100644 --- a/kotlinx-coroutines-core/jvm/test/RunInterruptibleStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/RunInterruptibleStressTest.kt @@ -9,25 +9,29 @@ import org.junit.Test import java.util.concurrent.atomic.* import kotlin.test.* +/** + * Stress test for [runInterruptible]. + * It does not pass on JDK 1.6 on Windows: [Thread.sleep] times out without being interrupted despite the + * fact that thread interruption flag is set. + */ class RunInterruptibleStressTest : TestBase() { - @get:Rule val dispatcher = ExecutorRule(4) - private val REPEAT_TIMES = 1000 * stressTestMultiplier + private val repeatTimes = 1000 * stressTestMultiplier @Test - fun testStress() = runBlocking { - val interruptLeak = AtomicBoolean(false) + fun testStress() = runTest { val enterCount = AtomicInteger(0) val interruptedCount = AtomicInteger(0) - repeat(REPEAT_TIMES) { + repeat(repeatTimes) { val job = launch(dispatcher) { try { runInterruptible { enterCount.incrementAndGet() try { - Thread.sleep(Long.MAX_VALUE) + Thread.sleep(10_000) + error("Sleep was not interrupted, Thread.isInterrupted=${Thread.currentThread().isInterrupted}") } catch (e: InterruptedException) { interruptedCount.incrementAndGet() throw e @@ -36,19 +40,17 @@ class RunInterruptibleStressTest : TestBase() { } catch (e: CancellationException) { // Expected } finally { - interruptLeak.set(interruptLeak.get() || Thread.currentThread().isInterrupted) + assertFalse(Thread.currentThread().isInterrupted, "Interrupt flag should not leak") } } // Add dispatch delay val cancelJob = launch(dispatcher) { job.cancel() } - - job.start() joinAll(job, cancelJob) } - - assertFalse(interruptLeak.get()) + println("Entered runInterruptible ${enterCount.get()} times") + assertTrue(enterCount.get() > 0) // ensure timing is Ok and we don't cancel it all prematurely assertEquals(enterCount.get(), interruptedCount.get()) } }