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