Index: src/test/org/apache/lucene/index/TestIndexReader.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexReader.java (revision 708628) +++ src/test/org/apache/lucene/index/TestIndexReader.java (working copy) @@ -1386,4 +1386,44 @@ r3.close(); } + + public void testFalseDirectoryAlreadyClosed() throws Throwable { + + String tempDir = System.getProperty("java.io.tmpdir"); + if (tempDir == null) + throw new RuntimeException("java.io.tmpdir undefined"); + File indexDir = new File(tempDir, "lucenetestdiralreadyclosed"); + + try { + FSDirectory dir = FSDirectory.getDirectory(indexDir); + IndexWriter w = new IndexWriter(indexDir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); + w.setUseCompoundFile(false); + Document doc = new Document(); + w.addDocument(doc); + w.close(); + assertTrue(new File(indexDir, "_0.fnm").delete()); + + IndexReader r = null; + try { + r = IndexReader.open(indexDir); + fail("did not hit expected exception"); + } catch (AlreadyClosedException ace) { + fail("should not have hit AlreadyClosedException"); + } catch (FileNotFoundException ioe) { + // expected + } + + // Make sure we really did close the dir inside IndexReader.open + dir.close(); + + try { + dir.fileExists("hi"); + fail("did not hit expected exception"); + } catch (AlreadyClosedException ace) { + // expected + } + } finally { + _TestUtil.rmDir(indexDir); + } + } } Index: src/java/org/apache/lucene/index/DirectoryIndexReader.java =================================================================== --- src/java/org/apache/lucene/index/DirectoryIndexReader.java (revision 708628) +++ src/java/org/apache/lucene/index/DirectoryIndexReader.java (working copy) @@ -96,26 +96,46 @@ DirectoryIndexReader reader; if (infos.size() == 1) { // index is optimized - reader = SegmentReader.get(readOnly, infos, infos.info(0), closeDirectory); + reader = SegmentReader.get(readOnly, infos, infos.info(0), false); } else if (readOnly) { - reader = new ReadOnlyMultiSegmentReader(directory, infos, closeDirectory); + reader = new ReadOnlyMultiSegmentReader(directory, infos, false); } else { - reader = new MultiSegmentReader(directory, infos, closeDirectory, false); + reader = new MultiSegmentReader(directory, infos, false, false); } reader.setDeletionPolicy(deletionPolicy); + reader.closeDirectory = closeDirectory; return reader; } }; - if (commit == null) - return (DirectoryIndexReader) finder.run(); - else { - if (directory != commit.getDirectory()) - throw new IOException("the specified commit does not match the specified Directory"); - // This can & will directly throw IOException if the - // specified commit point has been deleted: - return (DirectoryIndexReader) finder.doBody(commit.getSegmentsFileName()); + DirectoryIndexReader reader = null; + try { + if (commit == null) + reader = (DirectoryIndexReader) finder.run(); + else { + if (directory != commit.getDirectory()) + throw new IOException("the specified commit does not match the specified Directory"); + // This can & will directly throw IOException if the + // specified commit point has been deleted: + reader = (DirectoryIndexReader) finder.doBody(commit.getSegmentsFileName()); + } + } finally { + // We passed false above for closeDirectory so that + // the directory would not be closed before we were + // done retrying, so at this point if we truly failed + // to open a reader, which means an exception is being + // thrown, then close the directory now: + if (reader == null && closeDirectory) { + try { + directory.close(); + } catch (IOException ioe) { + // suppress, so we keep throwing original failure + // from opening the reader + } + } } + + return reader; } public final synchronized IndexReader reopen() throws CorruptIndexException, IOException {