8053931: (fc) FileDispatcherImpl.lock0 does not handle ERROR_IO_PENDING [win]

Doerr, Martin martin.doerr at sap.com
Thu Jul 31 08:08:59 UTC 2014


Hi Alan,

I've tried the official Oracle JVM jdk1.8.0_11 and it shows the same problem:

C:\temp>C:\Java\jdk1.8.0_11\bin\java -Djava.compiler=none -verify -classpath \\hs0131\hs0131.a\sapjvm_dev\jck\jck8\JCK-runtime-8\classes -Djava.security.policy=\\hs0131\hs0131.a\sapjvm_dev\jck\jck8\JCK-runtime-8\lib\jck.policy javasoft.sqe.tests.api.java.nio.channels.AsynchronousFileChannel.TryLockTests -TestURL file:////hs0131/hs0131.a/sapjvm_dev/jck/jck8/JCK-runtime-8/tests/api/java_nio/channels/AsynchronousFileChannel/AsynchronousFileChannel.html#tryLock -TestWorkDirURL file:/X:/certification/JCK-runtime-8/workdir/api/java_nio/channels/AsynchronousFileChannel/

In a first attempt, the JVM crashed with a broken stack (probably because the OVERLAPPED structure was modified after the frame was gone and something else was there).

In a second attempt, some subtests failed with the exception:
FAILED: Unexpected java.io.IOException: Overlapped I/O operation is in progress
(complete output below)

My machine is a desktop PC with a Core i7 870 (2.93 GHz) processor and a classical NTFS hard disk drive. Shouldn't be too special.
Maybe the windows version plays a role (Microsoft Windows [Version 6.2.9200]).

We have tried the fix from
http://cr.openjdk.java.net/~goetz/webrevs/8053931-tryLock/webrev-01/<http://cr.openjdk.java.net/%7Egoetz/webrevs/8053931-tryLock/webrev-01/>
with our JVM and it has solved the problem.

Please note that I'll be out for the next 11 days.

Best regards,
Martin



Complete output:

tryLock01_04: Passed. OKAY
tryLock02_01: Failed. FAILED
tryLock01_02: Passed. OKAY
tryLock01_05: Passed. OKAY
tryLock01_03: Failed. FAILED
tryLock01_09: Failed. FAILED
tryLock01_07: Passed. OKAY
tryLock01_08: Passed. OKAY
tryLock01_06: Passed. OKAY
tryLock02_02: Passed. OKAY
tryLock01_01: Passed. OKAY
==== tryLock01_04 ====
IllegalArgumentException was thrown asexpected
==== tryLock02_01 ====
FAILED: Unexpected java.io.IOException: Overlapped I/O operation is in progress
java.io.IOException: Overlapped I/O operation is in progress
        at sun.nio.ch.FileDispatcherImpl.lock0(Native Method)
        at sun.nio.ch.FileDispatcherImpl.lock(FileDispatcherImpl.java:102)
        at sun.nio.ch.WindowsAsynchronousFileChannelImpl.tryLock(WindowsAsynchronousFileChannelImpl.java:359)
        at java.nio.channels.AsynchronousFileChannel.tryLock(AsynchronousFileChannel.java:640)
        at javasoft.sqe.tests.api.java.nio.channels.AsynchronousFileChannel.TryLockTests$10.runTest(TryLockTests.java:399)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single.runTestSafely(Nio2TestCase.java:385)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single$1.run(Nio2TestCase.java:349)
        at javasoft.sqe.jck.lib.SecurityTestRunner.runTestWithTCKSM(SecurityTestRunner.java:279)
        at javasoft.sqe.jck.lib.SecurityTestRunner.runTestWithPermissions(SecurityTestRunner.java:235)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single.runTestWithPerms(Nio2TestCase.java:354)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single.runTestWithAllPermsDenied(Nio2TestCase.java:270)
        at javasoft.sqe.tests.api.java.nio.channels.AsynchronousFileChannel.TryLockTests.tryLock02_01(TryLockTests.java:406)
        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 javasoft.sqe.javatest.lib.MultiTest.invokeTestCase(MultiTest.java:405)
        at javasoft.sqe.javatest.lib.MultiTest.run(MultiTest.java:194)
        at javasoft.sqe.javatest.lib.MultiTest.run(MultiTest.java:126)
        at javasoft.sqe.tests.api.java.nio.channels.AsynchronousFileChannel.TryLockTests.main(TryLockTests.java:53)
==== tryLock01_02 ====
NonReadableChannelException was thrown as expected
==== tryLock01_05 ====
IllegalArgumentException was thrown asexpected
==== tryLock01_03 ====
FAILED: Unexpected java.io.IOException: Overlapped I/O operation is in progress
java.io.IOException: Overlapped I/O operation is in progress
        at sun.nio.ch.FileDispatcherImpl.lock0(Native Method)
        at sun.nio.ch.FileDispatcherImpl.lock(FileDispatcherImpl.java:102)
        at sun.nio.ch.WindowsAsynchronousFileChannelImpl.tryLock(WindowsAsynchronousFileChannelImpl.java:359)
        at javasoft.sqe.tests.api.java.nio.channels.AsynchronousFileChannel.TryLockTests$3.runTest(TryLockTests.java:154)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single.runTestSafely(Nio2TestCase.java:385)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single$1.run(Nio2TestCase.java:349)
        at javasoft.sqe.jck.lib.SecurityTestRunner.runTestWithTCKSM(SecurityTestRunner.java:279)
        at javasoft.sqe.jck.lib.SecurityTestRunner.runTestWithPermissions(SecurityTestRunner.java:235)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single.runTestWithPerms(Nio2TestCase.java:354)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single.runTestWithAllPermsDenied(Nio2TestCase.java:270)
        at javasoft.sqe.tests.api.java.nio.channels.AsynchronousFileChannel.TryLockTests.tryLock01_03(TryLockTests.java:166)
        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 javasoft.sqe.javatest.lib.MultiTest.invokeTestCase(MultiTest.java:405)
        at javasoft.sqe.javatest.lib.MultiTest.run(MultiTest.java:194)
        at javasoft.sqe.javatest.lib.MultiTest.run(MultiTest.java:126)
        at javasoft.sqe.tests.api.java.nio.channels.AsynchronousFileChannel.TryLockTests.main(TryLockTests.java:53)
==== tryLock01_09 ====
FAILED: Unexpected java.io.IOException: Overlapped I/O operation is in progress
java.io.IOException: Overlapped I/O operation is in progress
        at sun.nio.ch.FileDispatcherImpl.lock0(Native Method)
        at sun.nio.ch.FileDispatcherImpl.lock(FileDispatcherImpl.java:102)
        at sun.nio.ch.WindowsAsynchronousFileChannelImpl.tryLock(WindowsAsynchronousFileChannelImpl.java:359)
        at javasoft.sqe.tests.api.java.nio.channels.AsynchronousFileChannel.TryLockTests$9.runTest(TryLockTests.java:362)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single.runTestSafely(Nio2TestCase.java:385)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single$1.run(Nio2TestCase.java:349)
        at javasoft.sqe.jck.lib.SecurityTestRunner.runTestWithTCKSM(SecurityTestRunner.java:279)
        at javasoft.sqe.jck.lib.SecurityTestRunner.runTestWithPermissions(SecurityTestRunner.java:235)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single.runTestWithPerms(Nio2TestCase.java:354)
        at javasoft.sqe.tests.api.java.nio.Nio2TestCase$Single.runTestWithAllPermsDenied(Nio2TestCase.java:270)
        at javasoft.sqe.tests.api.java.nio.channels.AsynchronousFileChannel.TryLockTests.tryLock01_09(TryLockTests.java:374)
        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 javasoft.sqe.javatest.lib.MultiTest.invokeTestCase(MultiTest.java:405)
        at javasoft.sqe.javatest.lib.MultiTest.run(MultiTest.java:194)
        at javasoft.sqe.javatest.lib.MultiTest.run(MultiTest.java:126)
        at javasoft.sqe.tests.api.java.nio.channels.AsynchronousFileChannel.TryLockTests.main(TryLockTests.java:53)
==== tryLock01_07 ====
ClosedChannelException was thrown as expected
==== tryLock01_08 ====
OverlappingFileLockException was thrown as expected
==== tryLock01_06 ====
IllegalArgumentException was thrown asexpected
==== tryLock02_02 ====
NonWritableChannelException was thrown asexpected
==== tryLock01_01 ====
NonWritableChannelException was thrown as expected
STATUS:Failed.test cases: 11; passed: 8; failed: 3; first test case failure: tryLock02_01



From: Alan Bateman [mailto:Alan.Bateman at oracle.com]
Sent: Donnerstag, 31. Juli 2014 06:49
To: nio-dev
Cc: Doerr, Martin
Subject: Fwd: 8053931: (fc) FileDispatcherImpl.lock0 does not handle ERROR_IO_PENDING [win]


Forwarding Martin's mail, it seems to have got stuck because he was subscribed at the time.

Martin - one question about this, CreateFile isn't being opened with FILE_FLAG_OVERLAPPED so I'm curious if this is set in your port. I'm mostly asking because this code hasn't changed much since the original implementation in JDK 1.4 and I'm not aware of any reports of issues.

-Alan

From: Doerr, Martin
Sent: Mittwoch, 30. Juli 2014 13:08
To: 'nio-dev at openjdk.java.net<mailto:nio-dev at openjdk.java.net>'
Subject: 8053931: Fix bug in Java_sun_nio_ch_FileDispatcherImpl_lock0 (windows)

Hi all,

we have seen crashes and unexpected exceptions due to a bug in Java_sun_nio_ch_FileDispatcherImpl_lock0 under windows when running the jck test
"api/java_nio/channels/AsynchronousFileChannel/AsynchronousFileChannel.html#tryLock".
The exception text states "Overlapped I/O operation is in progress" which is the error returned by the windows API function "LockFileEx".

The c code contains the following. Note that LockFileEx works asynchronously in this test.
OVERLAPPED o;
...
result = LockFileEx(h, flags, 0, lowNumBytes, highNumBytes, &o);
...
no check for o afterwards!

With this current coding, Java_sun_nio_ch_FileDispatcherImpl_lock0 may return even though I/O is still pending. The asynchronous LockFileEx then modifies the OVERLAPPED o on stack which is no longer valid because the stack frame has gone.

According to Microsoft, this is not allowed:
-Do not deallocate or modify the OVERLAPPED structure or the data buffer until all asynchronous I/O operations to the file object have been completed.
-If you declare your pointer to the OVERLAPPED structure as a local variable, do not exit the local function until all asynchronous I/O operations to the file object have been completed. If the local function is exited prematurely, the OVERLAPPED structure will go out of scope and it will be inaccessible to any ReadFile or WriteFile functions it encounters outside of that function.
(http://msdn.microsoft.com/en-us/library/windows/desktop/aa365683%28v=vs.85%29.aspx)

The LockFileEx function is described here:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365203%28v=vs.85%29.aspx

A possible way to fix this problem, is to check for ERROR_IO_PENDING and use GetOverlappedResult to wait until the update to o has been completed and we can safely return if the locking has worked or not.
See webrev
http://cr.openjdk.java.net/~goetz/webrevs/8053931-tryLock/webrev-01/<http://cr.openjdk.java.net/%7Egoetz/webrevs/8053931-tryLock/webrev-01/>

We know that this defeats the purpose of being asynchronous to some extend, because GetOverlappedResult waits for the I/O in case of ERROR_IO_PENDING. Do we need to optimize this case and return to java to do something else? If yes, it requires to change the tryLock mechanism because the OVERLAPPED structure needs to get passed to someone who checks and frees it later.

Please note that I'll be out from 10/01 to 10/11. I just want to report this problem before I leave.

Best regards,
Martin



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/nio-dev/attachments/20140731/a0d06994/attachment-0001.html>


More information about the nio-dev mailing list