# HG changeset patch # User asaha # Date 1239985287 25200 # Node ID b49ee2080eb877ef5ec2ef73ef948012f8650b1d # Parent e49bc8fb5f2f488767289275d496cdb146208879# Parent a2ab3665456d869da6ad35328458ed3c554ed692 Merge diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java --- a/jdk/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java Fri Apr 17 09:21:27 2009 -0700 @@ -196,10 +196,12 @@ if ((start < 0) || (end > len) || (start > end)) throw new IndexOutOfBoundsException(); - int sublen = end - start; - int off = offset + ((pos + start) << $LG_BYTES_PER_VALUE$); - assert (off >= 0); - return new ByteBufferAsCharBuffer$RW$$BO$(bb, -1, 0, sublen, sublen, off); + return new ByteBufferAsCharBuffer$RW$$BO$(bb, + -1, + pos + start, + pos + end, + capacity(), + offset); } #end[char] diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/share/classes/java/nio/Direct-X-Buffer.java --- a/jdk/src/share/classes/java/nio/Direct-X-Buffer.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/share/classes/java/nio/Direct-X-Buffer.java Fri Apr 17 09:21:27 2009 -0700 @@ -412,10 +412,12 @@ if ((start < 0) || (end > len) || (start > end)) throw new IndexOutOfBoundsException(); - int sublen = end - start; - int off = (pos + start) << $LG_BYTES_PER_VALUE$; - assert (off >= 0); - return new DirectCharBuffer$RW$$BO$(this, -1, 0, sublen, sublen, off); + return new DirectCharBuffer$RW$$BO$(this, + -1, + pos + start, + pos + end, + capacity(), + offset); } #end[char] diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/share/classes/java/nio/Heap-X-Buffer.java --- a/jdk/src/share/classes/java/nio/Heap-X-Buffer.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/share/classes/java/nio/Heap-X-Buffer.java Fri Apr 17 09:21:27 2009 -0700 @@ -572,10 +572,13 @@ || (end > length()) || (start > end)) throw new IndexOutOfBoundsException(); - int len = end - start; + int pos = position(); return new HeapCharBuffer$RW$(hb, - -1, 0, len, len, - offset + position() + start); + -1, + pos + start, + pos + end, + capacity(), + offset); } #end[char] diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/share/classes/java/nio/StringCharBuffer.java --- a/jdk/src/share/classes/java/nio/StringCharBuffer.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/share/classes/java/nio/StringCharBuffer.java Fri Apr 17 09:21:27 2009 -0700 @@ -102,10 +102,12 @@ public final CharBuffer subSequence(int start, int end) { try { int pos = position(); - return new StringCharBuffer(str, -1, + return new StringCharBuffer(str, + -1, pos + checkIndex(start, pos), pos + checkIndex(end, pos), - remaining(), offset); + capacity(), + offset); } catch (IllegalArgumentException x) { throw new IndexOutOfBoundsException(); } diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java Fri Apr 17 09:21:27 2009 -0700 @@ -113,16 +113,16 @@ } } - final void invalidateAllLocks() { + final void invalidateAllLocks() throws IOException { if (fileLockTable != null) { - try { - fileLockTable.removeAll( new FileLockTable.Releaser() { - public void release(FileLock fl) { - ((FileLockImpl)fl).invalidate(); + for (FileLock fl: fileLockTable.removeAll()) { + synchronized (fl) { + if (fl.isValid()) { + FileLockImpl fli = (FileLockImpl)fl; + implRelease(fli); + fli.invalidate(); } - }); - } catch (IOException e) { - throw new AssertionError(e); + } } } } @@ -158,7 +158,21 @@ } /** - * Invoked by FileLockImpl to release lock acquired by this channel. + * Releases the given file lock. + */ + protected abstract void implRelease(FileLockImpl fli) throws IOException; + + /** + * Invoked by FileLockImpl to release the given file lock and remove it + * from the lock table. */ - abstract void release(FileLockImpl fli) throws IOException; + final void release(FileLockImpl fli) throws IOException { + try { + begin(); + implRelease(fli); + removeFromFileLockTable(fli); + } finally { + end(); + } + } } diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Fri Apr 17 09:21:27 2009 -0700 @@ -33,8 +33,6 @@ import java.nio.channels.*; import java.util.ArrayList; import java.util.List; -import java.util.Iterator; -import java.lang.reflect.Field; import java.security.AccessController; import javax.management.ObjectName; import javax.management.MalformedObjectNameException; @@ -95,14 +93,16 @@ // -- Standard channel operations -- protected void implCloseChannel() throws IOException { - // Invalidate and release any locks that we still hold + // Release and invalidate any locks that we still hold if (fileLockTable != null) { - fileLockTable.removeAll( new FileLockTable.Releaser() { - public void release(FileLock fl) throws IOException { - ((FileLockImpl)fl).invalidate(); - nd.release(fd, fl.position(), fl.size()); + for (FileLock fl: fileLockTable.removeAll()) { + synchronized (fl) { + if (fl.isValid()) { + nd.release(fd, fl.position(), fl.size()); + ((FileLockImpl)fl).invalidate(); + } } - }); + } } nd.preClose(fd); @@ -912,32 +912,33 @@ FileLockImpl fli = new FileLockImpl(this, position, size, shared); FileLockTable flt = fileLockTable(); flt.add(fli); - boolean i = true; + boolean completed = false; int ti = -1; try { begin(); ti = threads.add(); if (!isOpen()) return null; - int result = nd.lock(fd, true, position, size, shared); - if (result == FileDispatcher.RET_EX_LOCK) { - assert shared; - FileLockImpl fli2 = new FileLockImpl(this, position, size, - false); - flt.replace(fli, fli2); - return fli2; + int n; + do { + n = nd.lock(fd, true, position, size, shared); + } while ((n == FileDispatcher.INTERRUPTED) && isOpen()); + if (isOpen()) { + if (n == FileDispatcher.RET_EX_LOCK) { + assert shared; + FileLockImpl fli2 = new FileLockImpl(this, position, size, + false); + flt.replace(fli, fli2); + fli = fli2; + } + completed = true; } - if (result == FileDispatcher.INTERRUPTED || result == FileDispatcher.NO_LOCK) { + } finally { + if (!completed) flt.remove(fli); - i = false; - } - } catch (IOException e) { - flt.remove(fli); - throw e; - } finally { threads.remove(ti); try { - end(i); + end(completed); } catch (ClosedByInterruptException e) { throw new FileLockInterruptionException(); } @@ -985,7 +986,6 @@ } void release(FileLockImpl fli) throws IOException { - ensureOpen(); int ti = threads.add(); try { ensureOpen(); @@ -1005,7 +1005,7 @@ */ private static class SimpleFileLockTable extends FileLockTable { // synchronize on list for access - private List lockList = new ArrayList(2); + private final List lockList = new ArrayList(2); public SimpleFileLockTable() { } @@ -1034,14 +1034,11 @@ } } - public void removeAll(Releaser releaser) throws IOException { + public List removeAll() { synchronized(lockList) { - Iterator i = lockList.iterator(); - while (i.hasNext()) { - FileLock fl = i.next(); - releaser.release(fl); - i.remove(); - } + List result = new ArrayList(lockList); + lockList.clear(); + return result; } } diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/share/classes/sun/nio/ch/FileLockImpl.java --- a/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java Fri Apr 17 09:21:27 2009 -0700 @@ -31,25 +31,24 @@ public class FileLockImpl extends FileLock { - boolean valid; + private volatile boolean valid = true; FileLockImpl(FileChannel channel, long position, long size, boolean shared) { super(channel, position, size, shared); - this.valid = true; } FileLockImpl(AsynchronousFileChannel channel, long position, long size, boolean shared) { super(channel, position, size, shared); - this.valid = true; } - public synchronized boolean isValid() { + public boolean isValid() { return valid; } - synchronized void invalidate() { + void invalidate() { + assert Thread.holdsLock(this); valid = false; } @@ -66,5 +65,4 @@ valid = false; } } - } diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/share/classes/sun/nio/ch/FileLockTable.java --- a/jdk/src/share/classes/sun/nio/ch/FileLockTable.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/FileLockTable.java Fri Apr 17 09:21:27 2009 -0700 @@ -61,22 +61,11 @@ public abstract void remove(FileLock fl); /** - * An implementation of this interface releases a given file lock. - * Used with removeAll. + * Removes all file locks from the table. + * + * @return The list of file locks removed */ - public abstract interface Releaser { - void release(FileLock fl) throws IOException; - } - - /** - * Removes all file locks from the table. - *

- * The Releaser#release method is invoked for each file lock before - * it is removed. - * - * @throws IOException if the release method throws IOException - */ - public abstract void removeAll(Releaser r) throws IOException; + public abstract List removeAll(); /** * Replaces an existing file lock in the table. @@ -195,7 +184,7 @@ FileLockReference ref = list.get(index); FileLock lock = ref.get(); if (lock == fl) { - assert (lock != null) && (lock.channel() == channel); + assert (lock != null) && (lock.acquiredBy() == channel); ref.clear(); list.remove(index); break; @@ -206,7 +195,8 @@ } @Override - public void removeAll(Releaser releaser) throws IOException { + public List removeAll() { + List result = new ArrayList(); List list = lockMap.get(fileKey); if (list != null) { synchronized (list) { @@ -216,13 +206,13 @@ FileLock lock = ref.get(); // remove locks obtained by this channel - if (lock != null && lock.channel() == channel) { - // invoke the releaser to invalidate/release the lock - releaser.release(lock); - + if (lock != null && lock.acquiredBy() == channel) { // remove the lock from the list ref.clear(); list.remove(index); + + // add to result + result.add(lock); } else { index++; } @@ -232,6 +222,7 @@ removeKeyIfEmpty(fileKey, list); } } + return result; } @Override diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java Fri Apr 17 09:21:27 2009 -0700 @@ -97,6 +97,9 @@ // then it will throw ClosedChannelException } + // Invalidate and release any locks that we still hold + invalidateAllLocks(); + // signal any threads blocked on this channel nd.preClose(fdObj); threads.signalAndWait(); @@ -109,9 +112,6 @@ closeLock.writeLock().unlock(); } - // Invalidate and release any locks that we still hold - invalidateAllLocks(); - // close file nd.close(fdObj); @@ -226,11 +226,9 @@ do { n = nd.lock(fdObj, true, position, size, shared); } while ((n == FileDispatcher.INTERRUPTED) && isOpen()); - if (n == FileDispatcher.LOCKED) { + if (n == FileDispatcher.LOCKED && isOpen()) { result.setResult(fli); } else { - if (n != FileDispatcher.INTERRUPTED) - throw new AssertionError(); throw new AsynchronousCloseException(); } } catch (IOException x) { @@ -279,16 +277,16 @@ do { n = nd.lock(fdObj, false, position, size, shared); } while ((n == FileDispatcher.INTERRUPTED) && isOpen()); - if (n != FileDispatcher.LOCKED) { - if (n == FileDispatcher.NO_LOCK) - return null; // locked by someone else - if (n == FileDispatcher.INTERRUPTED) - throw new AsynchronousCloseException(); - // should not get here - throw new AssertionError(); + if (n == FileDispatcher.LOCKED && isOpen()) { + gotLock = true; + return fli; // lock acquired } - gotLock = true; - return fli; + if (n == FileDispatcher.NO_LOCK) + return null; // locked by someone else + if (n == FileDispatcher.INTERRUPTED) + throw new AsynchronousCloseException(); + // should not get here + throw new AssertionError(); } finally { if (!gotLock) removeFromFileLockTable(fli); @@ -298,14 +296,8 @@ } @Override - void release(FileLockImpl fli) throws IOException { - try { - begin(); - nd.release(fdObj, fli.position(), fli.size()); - removeFromFileLockTable(fli); - } finally { - end(); - } + protected void implRelease(FileLockImpl fli) throws IOException { + nd.release(fdObj, fli.position(), fli.size()); } @Override diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java --- a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java Fri Apr 17 09:21:27 2009 -0700 @@ -354,16 +354,9 @@ } } - // invoke by FileFileImpl to release lock @Override - void release(FileLockImpl fli) throws IOException { - try { - begin(); - nd.release(fdObj, fli.position(), fli.size()); - removeFromFileLockTable(fli); - } finally { - end(); - } + protected void implRelease(FileLockImpl fli) throws IOException { + nd.release(fdObj, fli.position(), fli.size()); } /** diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c --- a/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c Fri Apr 17 09:21:27 2009 -0700 @@ -414,7 +414,7 @@ o.Offset = lowPos; o.OffsetHigh = highPos; result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o); - if (result == 0) { + if (result == 0 && GetLastError() != ERROR_NOT_LOCKED) { JNU_ThrowIOExceptionWithLastError(env, "Release failed"); } } diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/Buffer/Basic-X.java --- a/jdk/test/java/nio/Buffer/Basic-X.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/Buffer/Basic-X.java Fri Apr 17 09:21:27 2009 -0700 @@ -365,8 +365,11 @@ b.position(2); ck(b, b.charAt(1), 'd'); - CharBuffer c = (CharBuffer)b.subSequence(1, 4); - ck(b, b.subSequence(1, 4).toString().equals("def")); + CharBuffer c = b.subSequence(1, 4); + ck(c, c.capacity(), b.capacity()); + ck(c, c.position(), b.position()+1); + ck(c, c.limit(), b.position()+4); + ck(c, b.subSequence(1, 4).toString().equals("def")); // 4938424 b.position(4); @@ -722,6 +725,8 @@ ck(b, start, b.position()); ck(b, end, b.limit()); ck(b, s.length(), b.capacity()); + b.position(6); + ck(b, b.subSequence(0,3).toString().equals("ghi")); // The index, relative to the position, must be non-negative and // smaller than remaining(). diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/Buffer/Basic.java --- a/jdk/test/java/nio/Buffer/Basic.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/Buffer/Basic.java Fri Apr 17 09:21:27 2009 -0700 @@ -25,7 +25,7 @@ * @summary Unit test for buffers * @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725 * 4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529 - * 6221101 6234263 6535542 6591971 6593946 + * 6221101 6234263 6535542 6591971 6593946 6795561 * @author Mark Reinhold */ diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/Buffer/BasicByte.java --- a/jdk/test/java/nio/Buffer/BasicByte.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/Buffer/BasicByte.java Fri Apr 17 09:21:27 2009 -0700 @@ -375,6 +375,9 @@ + + + // Compact relPut(b); @@ -786,6 +789,8 @@ + + public static void test(final byte [] ba) { int offset = 47; int length = 900; diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/Buffer/BasicChar.java --- a/jdk/test/java/nio/Buffer/BasicChar.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/Buffer/BasicChar.java Fri Apr 17 09:21:27 2009 -0700 @@ -365,8 +365,11 @@ b.position(2); ck(b, b.charAt(1), 'd'); - CharBuffer c = (CharBuffer)b.subSequence(1, 4); - ck(b, b.subSequence(1, 4).toString().equals("def")); + CharBuffer c = b.subSequence(1, 4); + ck(c, c.capacity(), b.capacity()); + ck(c, c.position(), b.position()+1); + ck(c, c.limit(), b.position()+4); + ck(c, b.subSequence(1, 4).toString().equals("def")); // 4938424 b.position(4); @@ -722,6 +725,8 @@ ck(b, start, b.position()); ck(b, end, b.limit()); ck(b, s.length(), b.capacity()); + b.position(6); + ck(b, b.subSequence(0,3).toString().equals("ghi")); // The index, relative to the position, must be non-negative and // smaller than remaining(). diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/Buffer/BasicDouble.java --- a/jdk/test/java/nio/Buffer/BasicDouble.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/Buffer/BasicDouble.java Fri Apr 17 09:21:27 2009 -0700 @@ -375,6 +375,9 @@ + + + // Compact relPut(b); @@ -786,6 +789,8 @@ + + public static void test(final double [] ba) { int offset = 47; int length = 900; diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/Buffer/BasicFloat.java --- a/jdk/test/java/nio/Buffer/BasicFloat.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/Buffer/BasicFloat.java Fri Apr 17 09:21:27 2009 -0700 @@ -375,6 +375,9 @@ + + + // Compact relPut(b); @@ -786,6 +789,8 @@ + + public static void test(final float [] ba) { int offset = 47; int length = 900; diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/Buffer/BasicInt.java --- a/jdk/test/java/nio/Buffer/BasicInt.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/Buffer/BasicInt.java Fri Apr 17 09:21:27 2009 -0700 @@ -375,6 +375,9 @@ + + + // Compact relPut(b); @@ -786,6 +789,8 @@ + + public static void test(final int [] ba) { int offset = 47; int length = 900; diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/Buffer/BasicLong.java --- a/jdk/test/java/nio/Buffer/BasicLong.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/Buffer/BasicLong.java Fri Apr 17 09:21:27 2009 -0700 @@ -375,6 +375,9 @@ + + + // Compact relPut(b); @@ -786,6 +789,8 @@ + + public static void test(final long [] ba) { int offset = 47; int length = 900; diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/Buffer/BasicShort.java --- a/jdk/test/java/nio/Buffer/BasicShort.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/Buffer/BasicShort.java Fri Apr 17 09:21:27 2009 -0700 @@ -375,6 +375,9 @@ + + + // Compact relPut(b); @@ -786,6 +789,8 @@ + + public static void test(final short [] ba) { int offset = 47; int length = 900; diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java --- a/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java Fri Apr 17 09:21:27 2009 -0700 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4607272 + * @bug 4607272 6822643 * @summary Unit test for AsynchronousFileChannel */ @@ -51,7 +51,6 @@ // run tests testUsingCompletionHandlers(ch); testUsingWaitOnResult(ch); - testLocking(ch); testInterruptHandlerThread(ch); // close channel and invoke test that expects channel to be closed @@ -59,6 +58,7 @@ testClosedChannel(ch); // these tests open the file themselves + testLocking(blah.toPath()); testCustomThreadPool(blah.toPath()); testAsynchronousClose(blah.toPath()); testCancel(blah.toPath()); @@ -160,47 +160,54 @@ } // exercise lock methods - static void testLocking(AsynchronousFileChannel ch) - throws IOException - { + static void testLocking(Path file) throws IOException { System.out.println("testLocking"); - // test 1 - acquire lock and check that tryLock throws - // OverlappingFileLockException + AsynchronousFileChannel ch = AsynchronousFileChannel + .open(file, READ, WRITE); FileLock fl; try { - fl = ch.lock().get(); - } catch (ExecutionException x) { - throw new RuntimeException(x); - } catch (InterruptedException x) { - throw new RuntimeException("Should not be interrupted"); - } - if (!fl.acquiredBy().equals(ch)) - throw new RuntimeException("FileLock#acquiredBy returned incorrect channel"); - try { - ch.tryLock(); - throw new RuntimeException("OverlappingFileLockException expected"); - } catch (OverlappingFileLockException x) { - } - fl.release(); + // test 1 - acquire lock and check that tryLock throws + // OverlappingFileLockException + try { + fl = ch.lock().get(); + } catch (ExecutionException x) { + throw new RuntimeException(x); + } catch (InterruptedException x) { + throw new RuntimeException("Should not be interrupted"); + } + if (!fl.acquiredBy().equals(ch)) + throw new RuntimeException("FileLock#acquiredBy returned incorrect channel"); + try { + ch.tryLock(); + throw new RuntimeException("OverlappingFileLockException expected"); + } catch (OverlappingFileLockException x) { + } + fl.release(); - // test 2 - acquire try and check that lock throws OverlappingFileLockException - fl = ch.tryLock(); - if (fl == null) - throw new RuntimeException("Unable to acquire lock"); - try { - ch.lock(null, new CompletionHandler () { - public void completed(FileLock result, Void att) { - } - public void failed(Throwable exc, Void att) { - } - public void cancelled(Void att) { - } - }); - throw new RuntimeException("OverlappingFileLockException expected"); - } catch (OverlappingFileLockException x) { + // test 2 - acquire try and check that lock throws OverlappingFileLockException + fl = ch.tryLock(); + if (fl == null) + throw new RuntimeException("Unable to acquire lock"); + try { + ch.lock(null, new CompletionHandler () { + public void completed(FileLock result, Void att) { + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + throw new RuntimeException("OverlappingFileLockException expected"); + } catch (OverlappingFileLockException x) { + } + } finally { + ch.close(); } - fl.release(); + + // test 3 - channel is closed so FileLock should no longer be valid + if (fl.isValid()) + throw new RuntimeException("FileLock expected to be invalid"); } // interrupt should not close channel diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java --- a/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java Thu Apr 16 22:47:29 2009 -0700 +++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java Fri Apr 17 09:21:27 2009 -0700 @@ -23,7 +23,7 @@ /* @test - * @bug 4607272 + * @bug 4607272 6814948 * @summary Unit test for AsynchronousFileChannel#lock method */ diff -r e49bc8fb5f2f -r b49ee2080eb8 jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java Fri Apr 17 09:21:27 2009 -0700 @@ -0,0 +1,98 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6543863 + * @summary Try to cause a deadlock between (Asynchronous)FileChannel.close + * and FileLock.release + */ + +import java.io.*; +import java.nio.file.Path; +import static java.nio.file.StandardOpenOption.*; +import java.nio.channels.*; +import java.util.concurrent.*; + +public class ReleaseOnCloseDeadlock { + private static final int LOCK_COUNT = 1024; + + public static void main(String[] args) throws IOException { + File blah = File.createTempFile("blah", null); + blah.deleteOnExit(); + for (int i=0; i<100; i++) { + test(blah.toPath()); + } + } + + static void test(Path file) throws IOException { + FileLock[] locks = new FileLock[LOCK_COUNT]; + + FileChannel fc = FileChannel.open(file, READ, WRITE); + for (int i=0; i