8137121: (fc) Infinite loop FileChannel.truncate
authorigerasim
Sat, 26 Sep 2015 00:23:15 +0300
changeset 32774 6a38398a04f7
parent 32773 6fb58bd2c745
child 32775 cab3b72f31b7
8137121: (fc) Infinite loop FileChannel.truncate Reviewed-by: alanb
jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
jdk/test/java/nio/channels/FileChannel/LoopingTruncate.java
--- a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java	Thu Sep 24 18:16:56 2015 +0000
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java	Sat Sep 26 00:23:15 2015 +0300
@@ -328,6 +328,7 @@
             int rv = -1;
             long p = -1;
             int ti = -1;
+            long rp = -1;
             try {
                 begin();
                 ti = threads.add();
@@ -363,8 +364,8 @@
                 if (p > newSize)
                     p = newSize;
                 do {
-                    rv = (int)position0(fd, p);
-                } while ((rv == IOStatus.INTERRUPTED) && isOpen());
+                    rp = position0(fd, p);
+                } while ((rp == IOStatus.INTERRUPTED) && isOpen());
                 return this;
             } finally {
                 threads.remove(ti);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/FileChannel/LoopingTruncate.java	Sat Sep 26 00:23:15 2015 +0300
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8137121
+ * @summary (fc) Infinite loop FileChannel.truncate
+ * @run main/othervm LoopingTruncate
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import static java.nio.file.StandardOpenOption.*;
+
+public class LoopingTruncate {
+
+    // (int)FATEFUL_SIZE == -3 == IOStatus.INTERRUPTED
+    static long FATEFUL_SIZE = 0x1FFFFFFFDL;
+
+    static long TIMEOUT = 10_000; // 10 seconds
+
+    public static void main(String[] args) throws Throwable {
+        Path path = Files.createTempFile("LoopingTruncate.tmp", null);
+        try {
+            Thread th = new Thread(() -> {
+                try (FileChannel fc = FileChannel.open(path, CREATE, WRITE)) {
+                    fc.position(FATEFUL_SIZE + 1L);
+                    fc.write(ByteBuffer.wrap(new byte[] {0}));
+                    fc.truncate(FATEFUL_SIZE);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }});
+            th.start();
+            th.join(TIMEOUT);
+
+            if (th.isAlive()) {
+                th.interrupt();
+                throw new RuntimeException("Failed to complete on time");
+            }
+        } finally {
+            Files.deleteIfExists(path);
+        }
+    }
+}