diff -r d66e420cc482 -r 98801bd22f5b test/jdk/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java --- a/test/jdk/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java Fri Dec 01 22:04:03 2017 -0800 +++ b/test/jdk/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java Sat Dec 02 10:03:41 2017 -0800 @@ -39,6 +39,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.locks.AbstractQueuedLongSynchronizer; import java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject; @@ -1283,4 +1284,57 @@ sync.release(); } + /** + * Tests scenario for + * JDK-8191937: Lost interrupt in AbstractQueuedSynchronizer when tryAcquire methods throw + */ + public void testInterruptedFailingAcquire() throws InterruptedException { + final RuntimeException ex = new RuntimeException(); + + // A synchronizer only offering a choice of failure modes + class Sync extends AbstractQueuedLongSynchronizer { + boolean pleaseThrow; + @Override protected boolean tryAcquire(long ignored) { + if (pleaseThrow) throw ex; + return false; + } + @Override protected long tryAcquireShared(long ignored) { + if (pleaseThrow) throw ex; + return -1; + } + @Override protected boolean tryRelease(long ignored) { + return true; + } + @Override protected boolean tryReleaseShared(long ignored) { + return true; + } + } + + final Sync s = new Sync(); + + final Thread thread = newStartedThread(new CheckedRunnable() { + public void realRun() { + try { + if (ThreadLocalRandom.current().nextBoolean()) + s.acquire(1); + else + s.acquireShared(1); + shouldThrow(); + } catch (Throwable t) { + assertSame(ex, t); + assertTrue(Thread.interrupted()); + } + }}); + waitForThreadToEnterWaitState(thread); + assertSame(thread, s.getFirstQueuedThread()); + assertTrue(s.hasQueuedPredecessors()); + assertTrue(s.hasQueuedThreads()); + assertEquals(1, s.getQueueLength()); + + s.pleaseThrow = true; + thread.interrupt(); + s.release(1); + awaitTermination(thread); + } + }