Index: src/test/org/apache/lucene/store/MockRAMDirectory.java =================================================================== --- src/test/org/apache/lucene/store/MockRAMDirectory.java (revision 635576) +++ src/test/org/apache/lucene/store/MockRAMDirectory.java (working copy) @@ -186,6 +186,9 @@ } private synchronized void deleteFile(String name, boolean forced) throws IOException { + + maybeThrowDeterministicException(); + if (crashed && !forced) throw new IOException("cannot delete after crash"); Index: src/test/org/apache/lucene/index/TestIndexWriter.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexWriter.java (revision 635576) +++ src/test/org/apache/lucene/index/TestIndexWriter.java (working copy) @@ -3231,4 +3231,54 @@ w.close(); dir.close(); } + + private static class FailOnlyInCommit extends MockRAMDirectory.Failure { + + boolean fail1, fail2; + + public void eval(MockRAMDirectory dir) throws IOException { + StackTraceElement[] trace = new Exception().getStackTrace(); + boolean isCommit = false; + boolean isDelete = false; + for (int i = 0; i < trace.length; i++) { + if ("org.apache.lucene.index.SegmentInfos".equals(trace[i].getClassName()) && "commit".equals(trace[i].getMethodName())) + isCommit = true; + if ("org.apache.lucene.store.MockRAMDirectory".equals(trace[i].getClassName()) && "deleteFile".equals(trace[i].getMethodName())) + isDelete = true; + } + + if (isCommit) { + if (!isDelete) { + fail1 = true; + throw new RuntimeException("now fail first"); + } else { + fail2 = true; + throw new IOException("now fail during delete"); + } + } + } + } + + // LUCENE-1214 + public void testExceptionsDuringCommit() throws Throwable { + MockRAMDirectory dir = new MockRAMDirectory(); + FailOnlyInCommit failure = new FailOnlyInCommit(); + IndexWriter w = new IndexWriter(dir, false, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); + Document doc = new Document(); + doc.add(new Field("field", "a field", Field.Store.YES, + Field.Index.TOKENIZED)); + w.addDocument(doc); + dir.failOn(failure); + try { + w.close(); + fail(); + } catch (IOException ioe) { + fail("expected only RuntimeException"); + } catch (RuntimeException re) { + // Expected + } + assertTrue(failure.fail1 && failure.fail2); + w.abort(); + dir.close(); + } } Index: src/java/org/apache/lucene/index/SegmentInfos.java =================================================================== --- src/java/org/apache/lucene/index/SegmentInfos.java (revision 635585) +++ src/java/org/apache/lucene/index/SegmentInfos.java (working copy) @@ -300,13 +300,29 @@ } finally { boolean success2 = false; try { - output.close(); - success2 = true; + if (!success) { + // We hit an exception above; try to close the file + // but suppress any exception: + try { + output.close(); + success2 = true; + } catch (Throwable t) { + // Suppress so we keep throwing the original exception + } + } else { + output.close(); + success2 = true; + } } finally { - if (!success || !success2) - // Try not to leave a truncated segments_N file in - // the index: - directory.deleteFile(segmentFileName); + if (!success || !success2) { + try { + // Try not to leave a truncated segments_N file in + // the index: + directory.deleteFile(segmentFileName); + } catch (Throwable t) { + // Suppress so we keep throwing the original exception + } + } } } @@ -738,7 +754,11 @@ final String segmentFileName = IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS, "", generation); - dir.deleteFile(segmentFileName); + try { + dir.deleteFile(segmentFileName); + } catch (Throwable t) { + // Suppress so we keep throwing the original exception + } } } @@ -758,8 +778,13 @@ dir.sync(fileName); success = true; } finally { - if (!success) - dir.deleteFile(fileName); + if (!success) { + try { + dir.deleteFile(fileName); + } catch (Throwable t) { + // Suppress so we keep throwing the original exception + } + } } } }