Index: lucene/src/java/org/apache/lucene/store/NativeFSLockFactory.java =================================================================== --- lucene/src/java/org/apache/lucene/store/NativeFSLockFactory.java (revision 939554) +++ lucene/src/java/org/apache/lucene/store/NativeFSLockFactory.java (working copy) @@ -17,6 +17,7 @@ * limitations under the License. */ +import java.lang.management.ManagementFactory; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.io.File; @@ -25,6 +26,8 @@ import java.util.HashSet; import java.util.Random; +import org.apache.lucene.util.ThreadInterruptedException; + /** *

Implements {@link LockFactory} using native OS file * locks. Note that because this LockFactory relies on @@ -78,12 +81,22 @@ lockDir.getAbsolutePath()); } - String randomLockName = "lucene-" + Long.toString(new Random().nextInt(), Character.MAX_RADIX) + "-test.lock"; + // add the RuntimeMXBean's name to the lock file, to lower the chance for + // name collisions when this code is invoked by multiple JVMs (such as in + // our tests). On most systems, the name includes the process Id. + String randomLockName = "lucene-" + + ManagementFactory.getRuntimeMXBean().getName() + "-" + + Long.toString(new Random().nextInt(), Character.MAX_RADIX) + + "-test.lock"; Lock l = makeLock(randomLockName); try { l.obtain(); l.release(); + } catch (LockReleaseFailedException e) { + // If the test lock failed to delete after all the attempts, attempt a + // delete when the JVM exits. + new File(lockDir, randomLockName).deleteOnExit(); } catch (IOException e) { RuntimeException e2 = new RuntimeException("Failed to acquire random test lock; please verify filesystem for lock directory '" + lockDir + "' supports locking"); e2.initCause(e); @@ -308,7 +321,26 @@ } } if (!path.delete()) - throw new LockReleaseFailedException("failed to delete " + path); + // This can happen in several scenarios: + // 1. The lock is released, but the file is being held by an external + // process, such as AntiVirus + // 2. When we acquire the test lock file, it might be (under rare + // circumstances) that two JVMs will use the same lock file, and one + // will succeed to delete the file, while the other will get 'false' + // from path.delete() + // Therefore, we check if the file exists at all, and if so, attempt + // a re-delete few ms later + if (path.exists()) { + try { + wait(100); + } catch (InterruptedException e) { + throw new ThreadInterruptedException(e); + } + // if the file still exists, and cannot be deleted, fail. + if (path.exists() && !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