7133499: (fc) FileChannel.read not preempted by asynchronous close on OS X
Volker Simonis
volker.simonis at gmail.com
Mon Jan 20 11:57:03 PST 2014
Hi Alan,
I've tried your patch with our port on AIX.
The good news is that it fixes:
java/nio/channels/AsynchronousFileChannel/Lock.java
on AIX as well.
The bad news is, that it doesn't seem to help for:
java/nio/channels/AsyncCloseAndInterrupt.java
Here's a stack trace of where the VM gets stuck:
TestThread-FileChannel/transferTo/interrupt" #12 daemon prio=5
os_prio=57 tid=0x0000000119c07800 nid=0x1310131 runnable [0x000000011
a1e3000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
at sun.nio.ch.FileDispatcherImpl.write(FileDispatcherImpl.java:60)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:51)
at sun.nio.ch.SinkChannelImpl.write(SinkChannelImpl.java:167)
- locked <0x0a000100255c9330> (a java.lang.Object)
at sun.nio.ch.FileChannelImpl.transferToTrustedChannel(FileChannelImpl.java:468)
at sun.nio.ch.FileChannelImpl.transferTo(FileChannelImpl.java:564)
at AsyncCloseAndInterrupt$18.doIO(AsyncCloseAndInterrupt.java:391)
at AsyncCloseAndInterrupt$Tester.go(AsyncCloseAndInterrupt.java:485)
at TestThread.run(TestThread.java:55)
"MainThread" #9 prio=5 os_prio=57 tid=0x0000000119289800 nid=0x2d50115
runnable [0x0000000119497000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.FileDispatcherImpl.preClose0(Native Method)
at sun.nio.ch.FileDispatcherImpl.preClose(FileDispatcherImpl.java:102)
at sun.nio.ch.SinkChannelImpl.implCloseSelectableChannel(SinkChannelImpl.java:88)
- locked <0x0a000100255c9340> (a java.lang.Object)
at java.nio.channels.spi.AbstractSelectableChannel.implCloseChannel(AbstractSelectableChannel.java:234)
at java.nio.channels.spi.AbstractInterruptibleChannel$1.interrupt(AbstractInterruptibleChannel.java:165)
- locked <0x0a000100255c9300> (a java.lang.Object)
at java.lang.Thread.interrupt(Thread.java:918)
- locked <0x0a000100255ceca0> (a java.lang.Object)
at AsyncCloseAndInterrupt.test(AsyncCloseAndInterrupt.java:573)
at AsyncCloseAndInterrupt.test(AsyncCloseAndInterrupt.java:609)
at AsyncCloseAndInterrupt.main(AsyncCloseAndInterrupt.java:680)
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:483)
at com.sun.javatest.regtest.MainWrapper$MainThread.run(MainWrapper.java:94)
at java.lang.Thread.run(Thread.java:744)
As you can see, it hangs in preclose, because it is also blocked in
write. I think here is where calling the interruptible write in my
initial change helped. But now, after I saw your solution here for
7133499 I wonder if the same technique you applied in
FileChannelImpl.implCloseChannel() wouldn't work here as well.
However if I naively call NativeThread.signal(th) before calling
nd.preClose(fd) in SinkChannelImpl.implCloseSelectableChannel() this
improves the situation only slightly, because the VM now hangs in a
read():
"TestThread-FileChannel/transferFrom/interrupt" #12 daemon prio=5
os_prio=57 tid=0x00000001199a0800 nid=0x429000f runnable
[0x0000000119f02000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
at sun.nio.ch.FileDispatcherImpl.read(FileDispatcherImpl.java:46)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SourceChannelImpl.read(SourceChannelImpl.java:167)
- locked <0x0a0001003ab1ee68> (a java.lang.Object)
at sun.nio.ch.FileChannelImpl.transferFromArbitraryChannel(FileChannelImpl.java:625)
at sun.nio.ch.FileChannelImpl.transferFrom(FileChannelImpl.java:663)
at AsyncCloseAndInterrupt$19.doIO(AsyncCloseAndInterrupt.java:401)
at AsyncCloseAndInterrupt$Tester.go(AsyncCloseAndInterrupt.java:485)
at TestThread.run(TestThread.java:55)
"main" #1 prio=5 os_prio=57 tid=0x000000011022c800 nid=0x50e0101
runnable [0x000000011021d000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.FileDispatcherImpl.preClose0(Native Method)
at sun.nio.ch.FileDispatcherImpl.preClose(FileDispatcherImpl.java:102)
at sun.nio.ch.SourceChannelImpl.implCloseSelectableChannel(SourceChannelImpl.java:88)
- locked <0x0a0001003ab1ee78> (a java.lang.Object)
at java.nio.channels.spi.AbstractSelectableChannel.implCloseChannel(AbstractSelectableChannel.java:234)
at java.nio.channels.spi.AbstractInterruptibleChannel$1.interrupt(AbstractInterruptibleChannel.java:165)
- locked <0x0a0001003ab1ee38> (a java.lang.Object)
at java.lang.Thread.interrupt(Thread.java:918)
- locked <0x0a0001003ab1f5b8> (a java.lang.Object)
at AsyncCloseAndInterrupt.test(AsyncCloseAndInterrupt.java:573)
at AsyncCloseAndInterrupt.test(AsyncCloseAndInterrupt.java:609)
at AsyncCloseAndInterrupt.main(AsyncCloseAndInterrupt.java:681)
So I wonder if we would have to wrap all Java-calls to
close()/preClose() with NativeThread.signal() and all calls to
IO-functions like read/write/fcntl with
NativeThreadSet.add()/remove()?
Maybe then its easier doing it in the native interface (i.e. the NET_
wrappers) to just mimic the "usual" behaviour on AIX?
Regards,
Volker
On Mon, Jan 20, 2014 at 1:03 PM, Alan Bateman <Alan.Bateman at oracle.com> wrote:
>
> One of the outstanding issues from the OS X port is that the async close of
> a FileChannel where there are threads blocked doing I/O operation does not
> work, instead close hang (potentially indefinitely, say when another thread
> is blocked waiting for a file lock to be acquired or where the file is
> something like a pipe or other type of file where you can block
> indefinitely). From what I can tell, it wasn't implemented in Apple's JDK6
> either.
>
> In order to fix this on OS X then close needs to signal all threads that are
> blocked in I/O operations, something we already do on Linux. The other part
> is removing the preClose (the dup2) from the closing of FileChannels as it
> is not needed when you can signal. The webrev with the proposed changes is
> here:
>
> http://cr.openjdk.java.net/~alanb/7133499/webrev/
>
> Fixing this issue means that two tests can be removed from the exclude list
> (there is third test removed from the exclude list too, that shouldn't have
> been there).
>
> -Alan.
More information about the nio-dev
mailing list