Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 889121) +++ CHANGES.txt (working copy) @@ -42,6 +42,9 @@ * LUCENE-2132: Fix the demo result.jsp to use QueryParser with a Version argument. (Brian Li via Robert Muir) + +* LUCENE-2104: NativeFSLock.release() would silently fail if the lock is held by + another thread/process. (Shai Erera via ?) New features Index: src/java/org/apache/lucene/store/NativeFSLockFactory.java =================================================================== --- src/java/org/apache/lucene/store/NativeFSLockFactory.java (revision 889121) +++ src/java/org/apache/lucene/store/NativeFSLockFactory.java (working copy) @@ -146,7 +146,7 @@ } } } -}; +} class NativeFSLock extends Lock { @@ -300,6 +300,22 @@ } if (!path.delete()) throw new LockReleaseFailedException("failed to delete " + path); + } else { + // if we don't hold the lock, and somebody still called release(), for + // example as a result of calling IndexWriter.unlock(), we should attempt + // to obtain the lock and release it. If the obtain fails, it means the + // lock cannot be released, and we should throw a proper exception rather + // than silently failing/not doing anything. + boolean obtained = false; + try { + if ((obtained = obtain()) == false) { + throw new LockReleaseFailedException("Lock held by another process and cannot be released: " + path); + } + } finally { + if (obtained) { + release(); + } + } } } Index: src/test/org/apache/lucene/store/TestLockFactory.java =================================================================== --- src/test/org/apache/lucene/store/TestLockFactory.java (revision 889121) +++ src/test/org/apache/lucene/store/TestLockFactory.java (working copy) @@ -198,6 +198,26 @@ assertFalse(l2.isLocked()); } + public void testNativeFSLockReleaseByOtherLock() throws IOException { + + NativeFSLockFactory f = new NativeFSLockFactory(System.getProperty("tempDir")); + + f.setLockPrefix("test"); + Lock l = f.makeLock("commit"); + Lock l2 = f.makeLock("commit"); + + assertTrue("failed to obtain lock", l.obtain()); + try { + assertTrue(l2.isLocked()); + l2.release(); + fail("should not have reached here. LockReleaseFailedException should have been thrown"); + } catch (IOException e) { + assertTrue("Unexpected exception", e instanceof LockReleaseFailedException); + } finally { + l.release(); + } + } + // Verify: NativeFSLockFactory assigns null as lockPrefix if the lockDir is inside directory public void testNativeFSLockFactoryPrefix() throws IOException {