Skip to content

Commit 64ca26a

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 c433c4e commit 64ca26a

File tree

3 files changed

+24
-323
lines changed

3 files changed

+24
-323
lines changed

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

+24
Original file line numberDiff line numberDiff line change
@@ -890,11 +890,35 @@ public void forceMerge(boolean flush) throws IOException {
890890
*/
891891
public abstract IndexCommitRef acquireIndexCommit(boolean flushFirst) throws EngineException;
892892

893+
/**
894+
* If the specified throwable contains a fatal error in the throwable graph, such a fatal error will be thrown. Callers should ensure
895+
* 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
896+
* by the uncaught exception handler that we install during bootstrap. If the specified throwable does indeed contain a fatal error, the
897+
* specified message will attempt to be logged before throwing the fatal error. If the specified throwable does not contain a fatal
898+
* error, this method is a no-op.
899+
*
900+
* @param maybeMessage the message to maybe log
901+
* @param maybeFatal the throwable that maybe contains a fatal error
902+
*/
903+
@SuppressWarnings("finally")
904+
private void maybeDie(final String maybeMessage, final Throwable maybeFatal) {
905+
ExceptionsHelper.maybeError(maybeFatal, logger).ifPresent(error -> {
906+
try {
907+
logger.error(maybeMessage, error);
908+
} finally {
909+
throw error;
910+
}
911+
});
912+
}
913+
893914
/**
894915
* fail engine due to some error. the engine will also be closed.
895916
* The underlying store is marked corrupted iff failure is caused by index corruption
896917
*/
897918
public void failEngine(String reason, @Nullable Exception failure) {
919+
if (failure != null) {
920+
maybeDie(reason, failure);
921+
}
898922
if (failEngineLock.tryLock()) {
899923
store.incRef();
900924
try {

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

-23
Original file line numberDiff line numberDiff line change
@@ -1701,7 +1701,6 @@ private boolean failOnTragicEvent(AlreadyClosedException ex) {
17011701
// we need to fail the engine. it might have already been failed before
17021702
// but we are double-checking it's failed and closed
17031703
if (indexWriter.isOpen() == false && indexWriter.getTragicException() != null) {
1704-
maybeDie("tragic event in index writer", indexWriter.getTragicException());
17051704
failEngine("already closed by tragic event on the index writer", (Exception) indexWriter.getTragicException());
17061705
engineFailed = true;
17071706
} else if (translog.isOpen() == false && translog.getTragicException() != null) {
@@ -2037,34 +2036,12 @@ protected void doRun() throws Exception {
20372036
* confidence that the call stack does not contain catch statements that would cause the error that might be thrown
20382037
* here from being caught and never reaching the uncaught exception handler.
20392038
*/
2040-
maybeDie("fatal error while merging", exc);
2041-
logger.error("failed to merge", exc);
20422039
failEngine("merge failed", new MergePolicy.MergeException(exc, dir));
20432040
}
20442041
});
20452042
}
20462043
}
20472044

2048-
/**
2049-
* If the specified throwable is a fatal error, this throwable will be thrown. Callers should ensure that there are no catch statements
2050-
* that would catch an error in the stack as the fatal error here should go uncaught and be handled by the uncaught exception handler
2051-
* that we install during bootstrap. If the specified throwable is indeed a fatal error, the specified message will attempt to be logged
2052-
* before throwing the fatal error. If the specified throwable is not a fatal error, this method is a no-op.
2053-
*
2054-
* @param maybeMessage the message to maybe log
2055-
* @param maybeFatal the throwable that is maybe fatal
2056-
*/
2057-
@SuppressWarnings("finally")
2058-
private void maybeDie(final String maybeMessage, final Throwable maybeFatal) {
2059-
if (maybeFatal instanceof Error) {
2060-
try {
2061-
logger.error(maybeMessage, maybeFatal);
2062-
} finally {
2063-
throw (Error) maybeFatal;
2064-
}
2065-
}
2066-
}
2067-
20682045
/**
20692046
* Commits the specified index writer.
20702047
*

server/src/main/java/org/elasticsearch/ExceptionsHelper.java

-300
This file was deleted.

0 commit comments

Comments
 (0)