Skip to content

Commit 72986db

Browse files
committed
Maybe die before failing engine (#28973)
Today we check for a few cases where we should maybe die before failing the engine (e.g., when a merge fails). However, there are still other cases where a fatal error can be hidden from us (for example, a failed index writer commit). This commit modifies the mechanism for failing the engine to always check for a fatal error before failing the engine.
1 parent 890ee15 commit 72986db

File tree

2 files changed

+24
-23
lines changed

2 files changed

+24
-23
lines changed

core/src/main/java/org/elasticsearch/index/engine/Engine.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,11 +785,35 @@ public void forceMerge(boolean flush) throws IOException {
785785
*/
786786
public abstract IndexCommit acquireIndexCommit(boolean flushFirst) throws EngineException;
787787

788+
/**
789+
* If the specified throwable contains a fatal error in the throwable graph, such a fatal error will be thrown. Callers should ensure
790+
* that there are no catch statements that would catch an error in the stack as the fatal error here should go uncaught and be handled
791+
* by the uncaught exception handler that we install during bootstrap. If the specified throwable does indeed contain a fatal error, the
792+
* specified message will attempt to be logged before throwing the fatal error. If the specified throwable does not contain a fatal
793+
* error, this method is a no-op.
794+
*
795+
* @param maybeMessage the message to maybe log
796+
* @param maybeFatal the throwable that maybe contains a fatal error
797+
*/
798+
@SuppressWarnings("finally")
799+
private void maybeDie(final String maybeMessage, final Throwable maybeFatal) {
800+
ExceptionsHelper.maybeError(maybeFatal, logger).ifPresent(error -> {
801+
try {
802+
logger.error(maybeMessage, error);
803+
} finally {
804+
throw error;
805+
}
806+
});
807+
}
808+
788809
/**
789810
* fail engine due to some error. the engine will also be closed.
790811
* The underlying store is marked corrupted iff failure is caused by index corruption
791812
*/
792813
public void failEngine(String reason, @Nullable Exception failure) {
814+
if (failure != null) {
815+
maybeDie(reason, failure);
816+
}
793817
if (failEngineLock.tryLock()) {
794818
store.incRef();
795819
try {

core/src/main/java/org/elasticsearch/index/engine/InternalEngine.java

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,6 @@ private boolean failOnTragicEvent(AlreadyClosedException ex) {
12331233
// we need to fail the engine. it might have already been failed before
12341234
// but we are double-checking it's failed and closed
12351235
if (indexWriter.isOpen() == false && indexWriter.getTragicException() != null) {
1236-
maybeDie("tragic event in index writer", indexWriter.getTragicException());
12371236
failEngine("already closed by tragic event on the index writer", (Exception) indexWriter.getTragicException());
12381237
engineFailed = true;
12391238
} else if (translog.isOpen() == false && translog.getTragicException() != null) {
@@ -1556,34 +1555,12 @@ protected void doRun() throws Exception {
15561555
* confidence that the call stack does not contain catch statements that would cause the error that might be thrown
15571556
* here from being caught and never reaching the uncaught exception handler.
15581557
*/
1559-
maybeDie("fatal error while merging", exc);
1560-
logger.error("failed to merge", exc);
15611558
failEngine("merge failed", new MergePolicy.MergeException(exc, dir));
15621559
}
15631560
});
15641561
}
15651562
}
15661563

1567-
/**
1568-
* If the specified throwable is a fatal error, this throwable will be thrown. Callers should ensure that there are no catch statements
1569-
* that would catch an error in the stack as the fatal error here should go uncaught and be handled by the uncaught exception handler
1570-
* that we install during bootstrap. If the specified throwable is indeed a fatal error, the specified message will attempt to be logged
1571-
* before throwing the fatal error. If the specified throwable is not a fatal error, this method is a no-op.
1572-
*
1573-
* @param maybeMessage the message to maybe log
1574-
* @param maybeFatal the throwable that is maybe fatal
1575-
*/
1576-
@SuppressWarnings("finally")
1577-
private void maybeDie(final String maybeMessage, final Throwable maybeFatal) {
1578-
if (maybeFatal instanceof Error) {
1579-
try {
1580-
logger.error(maybeMessage, maybeFatal);
1581-
} finally {
1582-
throw (Error) maybeFatal;
1583-
}
1584-
}
1585-
}
1586-
15871564
private void commitIndexWriter(IndexWriter writer, Translog translog, String syncId) throws IOException {
15881565
ensureCanFlush();
15891566
try {

0 commit comments

Comments
 (0)