Skip to content

Commit a28987a

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 0ca6b7e commit a28987a

File tree

2 files changed

+24
-23
lines changed

2 files changed

+24
-23
lines changed

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

+24
Original file line numberDiff line numberDiff line change
@@ -847,11 +847,35 @@ public void forceMerge(boolean flush) throws IOException {
847847
*/
848848
public abstract IndexCommitRef acquireSafeIndexCommit() throws EngineException;
849849

850+
/**
851+
* If the specified throwable contains a fatal error in the throwable graph, such a fatal error will be thrown. Callers should ensure
852+
* 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
853+
* by the uncaught exception handler that we install during bootstrap. If the specified throwable does indeed contain a fatal error, the
854+
* specified message will attempt to be logged before throwing the fatal error. If the specified throwable does not contain a fatal
855+
* error, this method is a no-op.
856+
*
857+
* @param maybeMessage the message to maybe log
858+
* @param maybeFatal the throwable that maybe contains a fatal error
859+
*/
860+
@SuppressWarnings("finally")
861+
private void maybeDie(final String maybeMessage, final Throwable maybeFatal) {
862+
ExceptionsHelper.maybeError(maybeFatal, logger).ifPresent(error -> {
863+
try {
864+
logger.error(maybeMessage, error);
865+
} finally {
866+
throw error;
867+
}
868+
});
869+
}
870+
850871
/**
851872
* fail engine due to some error. the engine will also be closed.
852873
* The underlying store is marked corrupted iff failure is caused by index corruption
853874
*/
854875
public void failEngine(String reason, @Nullable Exception failure) {
876+
if (failure != null) {
877+
maybeDie(reason, failure);
878+
}
855879
if (failEngineLock.tryLock()) {
856880
store.incRef();
857881
try {

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

-23
Original file line numberDiff line numberDiff line change
@@ -1788,7 +1788,6 @@ private boolean failOnTragicEvent(AlreadyClosedException ex) {
17881788
// we need to fail the engine. it might have already been failed before
17891789
// but we are double-checking it's failed and closed
17901790
if (indexWriter.isOpen() == false && indexWriter.getTragicException() != null) {
1791-
maybeDie("tragic event in index writer", indexWriter.getTragicException());
17921791
failEngine("already closed by tragic event on the index writer", (Exception) indexWriter.getTragicException());
17931792
engineFailed = true;
17941793
} else if (translog.isOpen() == false && translog.getTragicException() != null) {
@@ -2138,34 +2137,12 @@ protected void doRun() throws Exception {
21382137
* confidence that the call stack does not contain catch statements that would cause the error that might be thrown
21392138
* here from being caught and never reaching the uncaught exception handler.
21402139
*/
2141-
maybeDie("fatal error while merging", exc);
2142-
logger.error("failed to merge", exc);
21432140
failEngine("merge failed", new MergePolicy.MergeException(exc, dir));
21442141
}
21452142
});
21462143
}
21472144
}
21482145

2149-
/**
2150-
* If the specified throwable is a fatal error, this throwable will be thrown. Callers should ensure that there are no catch statements
2151-
* that would catch an error in the stack as the fatal error here should go uncaught and be handled by the uncaught exception handler
2152-
* that we install during bootstrap. If the specified throwable is indeed a fatal error, the specified message will attempt to be logged
2153-
* before throwing the fatal error. If the specified throwable is not a fatal error, this method is a no-op.
2154-
*
2155-
* @param maybeMessage the message to maybe log
2156-
* @param maybeFatal the throwable that is maybe fatal
2157-
*/
2158-
@SuppressWarnings("finally")
2159-
private void maybeDie(final String maybeMessage, final Throwable maybeFatal) {
2160-
if (maybeFatal instanceof Error) {
2161-
try {
2162-
logger.error(maybeMessage, maybeFatal);
2163-
} finally {
2164-
throw (Error) maybeFatal;
2165-
}
2166-
}
2167-
}
2168-
21692146
/**
21702147
* Commits the specified index writer.
21712148
*

0 commit comments

Comments
 (0)