Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8012019

(fc) Thread.interrupt triggers hang in FileChannelImpl.pread (win)

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P3
    • 8
    • 7, 7u17
    • core-libs
    • None
    • 7
    • b87
    • Verified

    Backports

      Description

        FULL PRODUCT VERSION :
        java version " 1.7.0_17 "
        Java(TM) SE Runtime Environment (build 1.7.0_17-b02)
        Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows [Version 6.1.7601]

        A DESCRIPTION OF THE PROBLEM :
        Our code frequently locks up when concurrent threads are reading the same file through NIO. I have created a test class that can be used to reproduce the issue. This is an example thread dump when the deadlock occurs:

        -----------------------------------------------------------------------
         " test thread 2 " prio=6 tid=0x01178400 nid=0x4b0 waiting for monitor entry [0x1967f000]
           java.lang.Thread.State: BLOCKED (on object monitor)
        at sun.nio.ch.FileDispatcherImpl.pread(FileDispatcherImpl.java:61)
        - waiting to lock <0x09d00c58> (a java.lang.Object)
        at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:222)
        at sun.nio.ch.IOUtil.read(IOUtil.java:198)
        at sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:674)
        at NioDeadlockTest$1.run(NioDeadlockTest.java:100)
        at java.lang.Thread.run(Thread.java:722)

           Locked ownable synchronizers:
        - None

         " test thread 1 " prio=6 tid=0x01177c00 nid=0xd08 in Object.wait() [0x194ef000]
           java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x09d00db8> (a sun.nio.ch.NativeThreadSet)
        at java.lang.Object.wait(Object.java:503)
        at sun.nio.ch.NativeThreadSet.signalAndWait(NativeThreadSet.java:102)
        - locked <0x09d00db8> (a sun.nio.ch.NativeThreadSet)
        at sun.nio.ch.FileChannelImpl.implCloseChannel(FileChannelImpl.java:114)
        at java.nio.channels.spi.AbstractInterruptibleChannel$1.interrupt(AbstractInterruptibleChannel.java:165)
        - locked <0x09d00dd0> (a java.lang.Object)
        at java.nio.channels.spi.AbstractInterruptibleChannel.begin(AbstractInterruptibleChannel.java:173)
        at sun.nio.ch.FileChannelImpl.size(FileChannelImpl.java:289)
        - locked <0x09d00c58> (a java.lang.Object)
        at NioDeadlockTest$1.run(NioDeadlockTest.java:102)
        at java.lang.Thread.run(Thread.java:722)

           Locked ownable synchronizers:
        - None

         " main " prio=6 tid=0x0037ec00 nid=0x1a40 waiting for monitor entry [0x00f0f000]
           java.lang.Thread.State: BLOCKED (on object monitor)
        at java.nio.channels.spi.AbstractInterruptibleChannel$1.interrupt(AbstractInterruptibleChannel.java:160)
        - waiting to lock <0x09d00dd0> (a java.lang.Object)
        at java.lang.Thread.interrupt(Thread.java:935)
        - locked <0x09d01410> (a java.lang.Object)
        at NioDeadlockTest.stopThread(NioDeadlockTest.java:81)
        at NioDeadlockTest.runTest(NioDeadlockTest.java:68)
        at NioDeadlockTest.main(NioDeadlockTest.java:25)

           Locked ownable synchronizers:
        - None
        -----------------------------------------------------------------------

        In this case, " test thread 1 " has been interrupted by the main thread and is attempting to close the file channel. It is waiting in NativeThreadSet.signalAndWait() for 'used' to count down to 0. " test thread 2 " is the one that is supposed to make this change by calling NativeThreadSet.remove(), but that thread is waiting for a lock (FileChannelImpl.positionLock) that is held by the first test thread. Finally, the main thread is also blocked, waiting for another lock that is held by the first test thread.

        This test fails with both the x64 and x86 versions of 1.7.0_17-b02, but it runs fine with 1.6.0_35-b10.

        REGRESSION. Last worked in version 6u31

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Run the supplied test class NioDeadlockTest.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The test class should complete the 100 test runs successfully.
        ACTUAL -
        The test freezes, often in the first 10 attempts.

        REPRODUCIBILITY :
        This bug can be reproduced often.

        ---------- BEGIN SOURCE ----------
        import java.io.File;
        import java.io.FileNotFoundException;
        import java.io.FileWriter;
        import java.io.IOException;
        import java.io.RandomAccessFile;
        import java.nio.ByteBuffer;
        import java.nio.channels.FileChannel;

        public class NioDeadlockTest {

        public static void main(String[] args)
        throws Exception
        {
        File tmpFile = File.createTempFile( " deadlock " , " .txt " );
        try {
        writeSomeText(tmpFile);

        for (int i = 1; i <= 100; i++) {
        System.out.println( " Attempt " + i);
        NioDeadlockTest test = new NioDeadlockTest(tmpFile);
        test.runTest();
        test.close();
        }
        }
        finally {
        tmpFile.delete();
        }
        }

        private static void writeSomeText(File file)
        throws IOException
        {
        FileWriter fw = new FileWriter(file);
        try {
        for (int i = 0; i < 1024; i++) {
        fw.write( " I shall never again run into a deadlock!
         " );
        }
        }
        finally {
        fw.close();
        }
        }

        private final RandomAccessFile raf;

        private final FileChannel fc;

        public NioDeadlockTest(File file)
        throws FileNotFoundException
        {
        raf = new RandomAccessFile(file, " r " );
        fc = raf.getChannel();
        }

        public void runTest()
        throws InterruptedException
        {
        Thread t1 = startTestThread(1);
        Thread t2 = startTestThread(2);

        Thread.sleep(100);

        stopThread(t1);
        stopThread(t2);
        }

        public void close()
        throws IOException
        {
        raf.close();
        }

        private void stopThread(Thread t)
        throws InterruptedException
        {
        System.out.println( " Interrupting thread " + t.getName());
        t.interrupt();
        t.join(5000);
        if (t.isAlive()) {
        System.out.println( " Failed to stop thread " + t.getName() + " ; deadlock? " );
        }
        }

        private Thread startTestThread(final int id) {
        Thread thread = new Thread(new Runnable() {

        private final ByteBuffer bb = ByteBuffer.allocate(1024);

        @Override
        public void run() {
        System.out.println( " > " + id);
        try {
        long pos = 0;
        while (true) {
        bb.clear();
        fc.read(bb, pos);
        pos += 1024;
        if (pos > fc.size()) {
        pos = 0;
        }
        }
        }
        catch (IOException e) {
        System.out.println(id + " : " + e.getClass());
        }
        finally {
        System.out.println( " < " + id);
        }
        }
        });
        thread.setName( " test thread " + id);
        thread.start();
        return thread;
        }
        }

        ---------- END SOURCE ----------

        Attachments

          Issue Links

            Activity

              People

                alanb Alan Bateman
                webbuggrp Webbug Group
                Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved: