JDK-8054039 : Deadlock during interrupting FileChannel
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 8,9,10
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • Submitted: 2014-07-31
  • Updated: 2018-03-01
  • Resolved: 2018-03-01
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
java/nio/channels/FileChannel/InterruptMapDeadlock.java
java/nio/channels/FileChannel/InterruptDeadlock.java

These two tests fail intermittently.

Example log for java/nio/channels/FileChannel/InterruptMapDeadlock.java:

----------System.out:(54/2715)----------
Iteration: 1
class java.nio.channels.ClosedByInterruptException (expected)
class java.nio.channels.AsynchronousCloseException (expected)
class java.nio.channels.AsynchronousCloseException (expected)
class java.nio.channels.AsynchronousCloseException (expected)
Iteration: 2
class java.nio.channels.AsynchronousCloseException (expected)
class java.nio.channels.ClosedByInterruptException (expected)
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedChannelException (expected)
Iteration: 3
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedByInterruptException (expected)
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedChannelException (expected)
Iteration: 4
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedByInterruptException (expected)
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedChannelException (expected)
Iteration: 5
class java.nio.channels.ClosedByInterruptException (expected)
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedChannelException (expected)
Iteration: 6
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedByInterruptException (expected)
class java.nio.channels.ClosedChannelException (expected)
Iteration: 7
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.AsynchronousCloseException (expected)
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedByInterruptException (expected)
Iteration: 8
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedByInterruptException (expected)
class java.nio.channels.AsynchronousCloseException (expected)
class java.nio.channels.ClosedChannelException (expected)
Iteration: 9
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.AsynchronousCloseException (expected)
class java.nio.channels.ClosedByInterruptException (expected)
class java.nio.channels.ClosedChannelException (expected)
Iteration: 10
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.ClosedByInterruptException (expected)
Iteration: 11
class java.nio.channels.ClosedChannelException (expected)
class java.nio.channels.AsynchronousCloseException (expected)
class java.nio.channels.AsynchronousCloseException (expected)
----------System.err:(26/1528)----------
Interruptor thread did not terminate:
java.lang.Exception: Stack trace
	at java.nio.channels.spi.AbstractInterruptibleChannel$1.interrupt(AbstractInterruptibleChannel.java:160)
	at java.lang.Thread.interrupt(Thread.java:919)
	at InterruptMapDeadlock$Interruptor.run(InterruptMapDeadlock.java:87)
Mapper thread did not terminate:
java.lang.Exception: Stack trace
	at java.lang.Thread.interrupt(Thread.java:915)
	at sun.nio.ch.NativeThreadSet.signalAndWait(NativeThreadSet.java:109)
	at sun.nio.ch.FileChannelImpl.implCloseChannel(FileChannelImpl.java:129)
	at java.nio.channels.spi.AbstractInterruptibleChannel$1.interrupt(AbstractInterruptibleChannel.java:165)
	at java.nio.channels.spi.AbstractInterruptibleChannel.begin(AbstractInterruptibleChannel.java:173)
	at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:854)
	at InterruptMapDeadlock$Mapper.run(InterruptMapDeadlock.java:53)
java.lang.RuntimeException: Test failed - see log for details
	at InterruptMapDeadlock.main(InterruptMapDeadlock.java:150)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:484)
	at com.sun.javatest.regtest.MainAction$SameVMRunnable.run(MainAction.java:759)
	at java.lang.Thread.run(Thread.java:745)

JavaTest Message: Test threw exception: java.lang.RuntimeException
JavaTest Message: shutting down test

result: Error. Error while cleaning up threads after test 
Comments
Issue is fixed in JDK-8198562.
01-03-2018

Yes, the fix of JDK-8198562 also fix this bug. I also verified by my test. Thanks to Alan!
01-03-2018

The issue here is calling Thread.currentThread.interrupt() while in a I/O operation (begin ... end). This issue has been fixed as part of JDK-8198562 so that the interrupt just sets the interrupt status. So I think we close this bug.
28-02-2018

fix #3 is a wrong solution in deed, because it blocks as before although it has no lock. So I am going to spend effort on verifying fix #1.
07-12-2015

fix #1: replace interrupt method with essential interrupt0 in NativeThreadSet.java to break the deadlock. fix #2: replace lock with CAS operation in AbstractInterruptibleChannel.java, it has a side effect -- close function has no wait, so the behavior changes, it's not safe because 3rd party code may have inherited AbstractInterruptibleChannel and may depend on current behavior. fix #3: based on fix #2, except no behavior change. But it has to use while loop to wait, once a large number of threads race, the performance will be terrible.
06-11-2015

Uploaded deadlock.png, which shows how the dead lock happens. Each vertical lane presents a thread. A rectangle box with having background color presents a procedure, if a procedure contains another procedure, that presents the contained procedure is a part of the parent procedure. There are 4 horizontal delimiters, each of them presents a time point, at that time, some procedure must happen before others of procedures. Thread 1 and thread 2 invoke map() on a same FileChannel, at same time, thread 3 is interrupting thread 2, if it happens to meet the conditions at the 4 time points, thread 2 will hold closeLock of the FileChannel and try to get the blockerLock of itself(i.e. thread 2), thread 3 will hold blockerLock of thread 2 and try to get closeLock of the FileChannel, that will result in the dead lock.
10-09-2015

If adding some delay code at some points, InterruptMapDeadlock.java will fail very easy. Refer to attached deadlock.diff
10-09-2015

The root cause is: the mapper thread holds closeLock ot the FileChannel and then is trying to get blockerLock of the mapper thread self, meanwhile the interruptor thread (which I talked here is the Interruptor class in InterruptMapDeadlock.java) holds blockerLock of the mapper thread and then is trying to get closeLock ot the FileChannel. This issue can happen when any FileChannel I/O operation is being interrupted.
11-05-2015