< prev index next >

src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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.  Oracle designates this

@@ -40,10 +40,11 @@
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.SelectableChannel;
 import java.nio.channels.WritableByteChannel;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import jdk.internal.misc.JavaIOFileDescriptorAccess;
 import jdk.internal.misc.JavaNioAccess;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.ref.Cleaner;

@@ -130,10 +131,22 @@
                     }
                 }
             }
         }
 
+        // Release and invalidate any orphaned locks still held
+        if (fileLockStates != null) {
+            for (FileLockState fls : fileLockStates) {
+                synchronized (fls) {
+                    if (fls.isValid()) {
+                        nd.release(fd, fls.position, fls.size);
+                        fls.invalidate();
+                    }
+                }
+            }
+        }
+
         // signal any threads blocked on this channel
         threads.signalAndWait();
 
         if (parent != null) {
 

@@ -1018,10 +1031,13 @@
 
     // indicates if the disableSystemWideOverlappingFileLockCheck property
     // has been checked
     private static volatile boolean propertyChecked;
 
+    // States of locks acquired on the channel
+    private volatile List<FileLockState> fileLockStates;
+
     // The lock list in J2SE 1.4/5.0 was local to each FileChannel instance so
     // the overlap check wasn't system wide when there were multiple channels to
     // the same file. This property is used to get 1.4/5.0 behavior if desired.
     private static boolean isSharedFileLockTable() {
         if (!propertyChecked) {

@@ -1056,10 +1072,21 @@
             }
         }
         return fileLockTable;
     }
 
+    private List<FileLockState> fileLockStates() {
+        if (fileLockStates == null) {
+            synchronized (this) {
+                if (fileLockStates == null) {
+                    fileLockStates = new CopyOnWriteArrayList<FileLockState>();
+                }
+            }
+        }
+        return fileLockStates;
+    }
+
     public FileLock lock(long position, long size, boolean shared)
         throws IOException
     {
         ensureOpen();
         if (shared && !readable)

@@ -1067,10 +1094,12 @@
         if (!shared && !writable)
             throw new NonWritableChannelException();
         FileLockImpl fli = new FileLockImpl(this, position, size, shared);
         FileLockTable flt = fileLockTable();
         flt.add(fli);
+        List<FileLockState> fls = fileLockStates();
+        fls.add(fli.getState());
         boolean completed = false;
         int ti = -1;
         try {
             begin();
             ti = threads.add();

@@ -1084,17 +1113,21 @@
                 if (n == FileDispatcher.RET_EX_LOCK) {
                     assert shared;
                     FileLockImpl fli2 = new FileLockImpl(this, position, size,
                                                          false);
                     flt.replace(fli, fli2);
+                    fls.remove(fli.getState());
                     fli = fli2;
+                    fls.add(fli.getState());
                 }
                 completed = true;
             }
         } finally {
-            if (!completed)
+            if (!completed) {
                 flt.remove(fli);
+                fls.remove(fli.getState());
+            }
             threads.remove(ti);
             try {
                 end(completed);
             } catch (ClosedByInterruptException e) {
                 throw new FileLockInterruptionException();

@@ -1112,30 +1145,36 @@
         if (!shared && !writable)
             throw new NonWritableChannelException();
         FileLockImpl fli = new FileLockImpl(this, position, size, shared);
         FileLockTable flt = fileLockTable();
         flt.add(fli);
+        List<FileLockState> fls = fileLockStates();
+        fls.add(fli.getState());
         int result;
 
         int ti = threads.add();
         try {
             try {
                 ensureOpen();
                 result = nd.lock(fd, false, position, size, shared);
             } catch (IOException e) {
                 flt.remove(fli);
+                fls.remove(fli.getState());
                 throw e;
             }
             if (result == FileDispatcher.NO_LOCK) {
                 flt.remove(fli);
+                fls.remove(fli.getState());
                 return null;
             }
             if (result == FileDispatcher.RET_EX_LOCK) {
                 assert shared;
                 FileLockImpl fli2 = new FileLockImpl(this, position, size,
                                                      false);
                 flt.replace(fli, fli2);
+                fls.remove(fli.getState());
+                fls.add(fli2.getState());
                 return fli2;
             }
             return fli;
         } finally {
             threads.remove(ti);
< prev index next >