@@ -1579,23 +1579,15 @@ public IndexCommitRef acquireIndexCommit(final boolean flushFirst) throws Engine
15791579 }
15801580 }
15811581
1582- @ SuppressWarnings ("finally" )
15831582 private boolean failOnTragicEvent (AlreadyClosedException ex ) {
15841583 final boolean engineFailed ;
15851584 // if we are already closed due to some tragic exception
15861585 // we need to fail the engine. it might have already been failed before
15871586 // but we are double-checking it's failed and closed
15881587 if (indexWriter .isOpen () == false && indexWriter .getTragicException () != null ) {
1589- if (indexWriter .getTragicException () instanceof Error ) {
1590- try {
1591- logger .error ("tragic event in index writer" , ex );
1592- } finally {
1593- throw (Error ) indexWriter .getTragicException ();
1594- }
1595- } else {
1596- failEngine ("already closed by tragic event on the index writer" , (Exception ) indexWriter .getTragicException ());
1597- engineFailed = true ;
1598- }
1588+ maybeDie ("tragic event in index writer" , indexWriter .getTragicException ());
1589+ failEngine ("already closed by tragic event on the index writer" , (Exception ) indexWriter .getTragicException ());
1590+ engineFailed = true ;
15991591 } else if (translog .isOpen () == false && translog .getTragicException () != null ) {
16001592 failEngine ("already closed by tragic event on the translog" , translog .getTragicException ());
16011593 engineFailed = true ;
@@ -1916,7 +1908,6 @@ protected void doRun() throws Exception {
19161908
19171909 @ Override
19181910 protected void handleMergeException (final Directory dir , final Throwable exc ) {
1919- logger .error ("failed to merge" , exc );
19201911 engineConfig .getThreadPool ().generic ().execute (new AbstractRunnable () {
19211912 @ Override
19221913 public void onFailure (Exception e ) {
@@ -1925,13 +1916,39 @@ public void onFailure(Exception e) {
19251916
19261917 @ Override
19271918 protected void doRun () throws Exception {
1928- MergePolicy .MergeException e = new MergePolicy .MergeException (exc , dir );
1929- failEngine ("merge failed" , e );
1919+ /*
1920+ * We do this on another thread rather than the merge thread that we are initially called on so that we have complete
1921+ * confidence that the call stack does not contain catch statements that would cause the error that might be thrown
1922+ * here from being caught and never reaching the uncaught exception handler.
1923+ */
1924+ maybeDie ("fatal error while merging" , exc );
1925+ logger .error ("failed to merge" , exc );
1926+ failEngine ("merge failed" , new MergePolicy .MergeException (exc , dir ));
19301927 }
19311928 });
19321929 }
19331930 }
19341931
1932+ /**
1933+ * If the specified throwable is a fatal error, this throwable will be thrown. Callers should ensure that there are no catch statements
1934+ * that would catch an error in the stack as the fatal error here should go uncaught and be handled by the uncaught exception handler
1935+ * that we install during bootstrap. If the specified throwable is indeed a fatal error, the specified message will attempt to be logged
1936+ * before throwing the fatal error. If the specified throwable is not a fatal error, this method is a no-op.
1937+ *
1938+ * @param maybeMessage the message to maybe log
1939+ * @param maybeFatal the throwable that is maybe fatal
1940+ */
1941+ @ SuppressWarnings ("finally" )
1942+ private void maybeDie (final String maybeMessage , final Throwable maybeFatal ) {
1943+ if (maybeFatal instanceof Error ) {
1944+ try {
1945+ logger .error (maybeMessage , maybeFatal );
1946+ } finally {
1947+ throw (Error ) maybeFatal ;
1948+ }
1949+ }
1950+ }
1951+
19351952 /**
19361953 * Commits the specified index writer.
19371954 *
0 commit comments