diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index c3bc61d12bc..51cb9d8a8df 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -183,6 +183,8 @@ Changes in Runtime Behavior * GITHUB#13293: ConcurrentMergeScheduler now allows up to 50% of the threads of the host to be used for merging. (Adrien Grand) +* GITHUB#13277: IndexWriter treats any java.lang.Error as tragic. (Robert Muir) + Changes in Backwards Compatibility Policy ----------------------------------------- diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java index 1f20cbd169a..7227ed56f34 100644 --- a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java +++ b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java @@ -153,9 +153,9 @@ import org.apache.lucene.util.Version; * and it decides when and how to run the merges. The default is {@link ConcurrentMergeScheduler}. * * - *
NOTE: if you hit a VirtualMachineError, or disaster strikes during a checkpoint then - * IndexWriter will close itself. This is a defensive measure in case any internal state (buffered - * documents, deletions, reference counts) were corrupted. Any subsequent calls will throw an + *
NOTE: if you hit an Error, or disaster strikes during a checkpoint then IndexWriter + * will close itself. This is a defensive measure in case any internal state (buffered documents, + * deletions, reference counts) were corrupted. Any subsequent calls will throw an * AlreadyClosedException. * *
NOTE: {@link IndexWriter} instances are completely thread safe, meaning multiple
@@ -704,7 +704,7 @@ public class IndexWriter
infoStream.message("IW", "getReader took " + (System.currentTimeMillis() - tStart) + " ms");
}
success2 = true;
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "getReader");
throw tragedy;
} finally {
@@ -1549,7 +1549,7 @@ public class IndexWriter
final long seqNo = maybeProcessEvents(docWriter.updateDocuments(docs, delNode));
success = true;
return seqNo;
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "updateDocuments");
throw tragedy;
} finally {
@@ -1786,7 +1786,7 @@ public class IndexWriter
ensureOpen();
try {
return maybeProcessEvents(docWriter.deleteTerms(terms));
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "deleteDocuments(Term..)");
throw tragedy;
}
@@ -1813,7 +1813,7 @@ public class IndexWriter
try {
return maybeProcessEvents(docWriter.deleteQueries(queries));
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "deleteDocuments(Query..)");
throw tragedy;
}
@@ -1892,7 +1892,7 @@ public class IndexWriter
try {
return maybeProcessEvents(
docWriter.updateDocValues(new NumericDocValuesUpdate(term, field, value)));
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "updateNumericDocValue");
throw tragedy;
}
@@ -1922,7 +1922,7 @@ public class IndexWriter
try {
return maybeProcessEvents(
docWriter.updateDocValues(new BinaryDocValuesUpdate(term, field, value)));
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "updateBinaryDocValue");
throw tragedy;
}
@@ -1944,7 +1944,7 @@ public class IndexWriter
DocValuesUpdate[] dvUpdates = buildDocValuesUpdate(term, updates);
try {
return maybeProcessEvents(docWriter.updateDocValues(dvUpdates));
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "updateDocValues");
throw tragedy;
}
@@ -2577,7 +2577,7 @@ public class IndexWriter
} catch (Throwable t) {
throwable.addSuppressed(t);
} finally {
- if (throwable instanceof VirtualMachineError) {
+ if (throwable instanceof Error) {
try {
tragicEvent(throwable, "rollbackInternal");
} catch (Throwable t1) {
@@ -2678,7 +2678,7 @@ public class IndexWriter
}
}
}
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "deleteAll");
throw tragedy;
}
@@ -3098,7 +3098,7 @@ public class IndexWriter
successTop = true;
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "addIndexes(Directory...)");
throw tragedy;
} finally {
@@ -3270,7 +3270,7 @@ public class IndexWriter
throw new RuntimeException(
"failed to successfully merge all provided readers in addIndexes(CodecReader...)");
}
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "addIndexes(CodecReader...)");
throw tragedy;
}
@@ -3623,7 +3623,7 @@ public class IndexWriter
return true; // we wrote a segment
}
return false;
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "flushNextBuffer");
throw tragedy;
} finally {
@@ -3739,7 +3739,7 @@ public class IndexWriter
doAfterFlush();
}
}
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "prepareCommit");
throw tragedy;
} finally {
@@ -4299,7 +4299,7 @@ public class IndexWriter
success = true;
return anyChanges;
}
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "doFlush");
throw tragedy;
} finally {
@@ -5693,7 +5693,7 @@ public class IndexWriter
segmentInfos.updateGeneration(toSync);
}
}
- } catch (VirtualMachineError tragedy) {
+ } catch (Error tragedy) {
tragicEvent(tragedy, "startCommit");
throw tragedy;
}
diff --git a/lucene/core/src/java/org/apache/lucene/util/IOUtils.java b/lucene/core/src/java/org/apache/lucene/util/IOUtils.java
index 0b4273dd4d5..3840eb60948 100644
--- a/lucene/core/src/java/org/apache/lucene/util/IOUtils.java
+++ b/lucene/core/src/java/org/apache/lucene/util/IOUtils.java
@@ -105,21 +105,20 @@ public final class IOUtils {
}
/**
- * Closes all given Closeable
s, suppressing all thrown non {@link
- * VirtualMachineError} exceptions. Even if a {@link VirtualMachineError} is thrown all given
- * closeable are closed.
+ * Closes all given Closeable
s, suppressing all thrown non {@link Error} exceptions.
+ * Even if a {@link Error} is thrown all given closeable are closed.
*
* @see #closeWhileHandlingException(Closeable...)
*/
public static void closeWhileHandlingException(Iterable extends Closeable> objects) {
- VirtualMachineError firstError = null;
+ Error firstError = null;
Throwable firstThrowable = null;
for (Closeable object : objects) {
try {
if (object != null) {
object.close();
}
- } catch (VirtualMachineError e) {
+ } catch (Error e) {
firstError = useOrSuppress(firstError, e);
} catch (Throwable t) {
firstThrowable = useOrSuppress(firstThrowable, t);
@@ -128,7 +127,7 @@ public final class IOUtils {
if (firstError != null) {
// we ensure that we bubble up any errors. We can't recover from these but need to make sure
// they are
- // bubbled up. if a non-VMError is thrown we also add the suppressed exceptions to it.
+ // bubbled up. if a non-Error is thrown we also add the suppressed exceptions to it.
if (firstThrowable != null) {
firstError.addSuppressed(firstThrowable);
}
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnVMError.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnError.java
similarity index 88%
rename from lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnVMError.java
rename to lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnError.java
index 10a6f4878e6..6bb83e50a1d 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnVMError.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnError.java
@@ -19,6 +19,7 @@ package org.apache.lucene.index;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.ByteArrayOutputStream;
+import java.io.IOError;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
@@ -53,7 +54,7 @@ import org.apache.lucene.util.IOUtils;
* index corruption is ever created.
*/
@SuppressCodecs("SimpleText")
-public class TestIndexWriterOnVMError extends LuceneTestCase {
+public class TestIndexWriterOnError extends LuceneTestCase {
// just one thread, serial merge policy, hopefully debuggable
private void doTest(MockDirectoryWrapper.Failure failOn) throws Exception {
@@ -151,7 +152,7 @@ public class TestIndexWriterOnVMError extends LuceneTestCase {
"dv2",
new BytesRef(Integer.toString(i + 1)));
}
- } catch (VirtualMachineError | AlreadyClosedException disaster) {
+ } catch (Error | AlreadyClosedException disaster) {
getTragedy(disaster, iw, exceptionStream);
continue STARTOVER;
}
@@ -174,7 +175,7 @@ public class TestIndexWriterOnVMError extends LuceneTestCase {
iw.deleteDocuments(
new Term("id", Integer.toString(i)), new Term("id", Integer.toString(-i)));
}
- } catch (VirtualMachineError | AlreadyClosedException disaster) {
+ } catch (Error | AlreadyClosedException disaster) {
getTragedy(disaster, iw, exceptionStream);
continue STARTOVER;
}
@@ -197,7 +198,7 @@ public class TestIndexWriterOnVMError extends LuceneTestCase {
if (DirectoryReader.indexExists(dir)) {
TestUtil.checkIndex(dir);
}
- } catch (VirtualMachineError | AlreadyClosedException disaster) {
+ } catch (Error | AlreadyClosedException disaster) {
getTragedy(disaster, iw, exceptionStream);
continue STARTOVER;
}
@@ -206,7 +207,7 @@ public class TestIndexWriterOnVMError extends LuceneTestCase {
try {
iw.close();
- } catch (VirtualMachineError | AlreadyClosedException disaster) {
+ } catch (Error | AlreadyClosedException disaster) {
getTragedy(disaster, iw, exceptionStream);
continue STARTOVER;
}
@@ -225,15 +226,13 @@ public class TestIndexWriterOnVMError extends LuceneTestCase {
}
}
- private VirtualMachineError getTragedy(Throwable disaster, IndexWriter writer, PrintStream log) {
+ private Error getTragedy(Throwable disaster, IndexWriter writer, PrintStream log) {
Throwable e = disaster;
if (e instanceof AlreadyClosedException) {
e = e.getCause();
}
- if (e instanceof VirtualMachineError
- && e.getMessage() != null
- && e.getMessage().startsWith("Fake")) {
+ if (e instanceof Error && e.getMessage() != null && e.getMessage().contains("Fake")) {
log.println("\nTEST: got expected fake exc:" + e.getMessage());
e.printStackTrace(log);
// TODO: remove rollback here, and add this assert to ensure "full OOM protection" anywhere IW
@@ -244,7 +243,7 @@ public class TestIndexWriterOnVMError extends LuceneTestCase {
} catch (Throwable t) {
t.printStackTrace(log);
}
- return (VirtualMachineError) e;
+ return (Error) e;
} else {
Rethrow.rethrow(disaster);
return null; // dead
@@ -281,6 +280,36 @@ public class TestIndexWriterOnVMError extends LuceneTestCase {
});
}
+ public void testLinkageError() throws Exception {
+ final Random r = new Random(random().nextLong());
+ doTest(
+ new Failure() {
+ @Override
+ public void eval(MockDirectoryWrapper dir) throws IOException {
+ if (r.nextInt(3000) == 0) {
+ if (callStackContains(IndexWriter.class)) {
+ throw new LinkageError("Fake LinkageError");
+ }
+ }
+ }
+ });
+ }
+
+ public void testIOError() throws Exception {
+ final Random r = new Random(random().nextLong());
+ doTest(
+ new Failure() {
+ @Override
+ public void eval(MockDirectoryWrapper dir) throws IOException {
+ if (r.nextInt(3000) == 0) {
+ if (callStackContains(IndexWriter.class)) {
+ throw new IOError(new RuntimeException("Fake IOError"));
+ }
+ }
+ }
+ });
+ }
+
@Nightly
public void testCheckpoint() throws Exception {
final Random r = new Random(random().nextLong());