2016-07-07 14:44:03 -04:00
|
|
|
/*
|
|
|
|
* Licensed to Elasticsearch under one or more contributor
|
|
|
|
* license agreements. See the NOTICE file distributed with
|
|
|
|
* this work for additional information regarding copyright
|
|
|
|
* ownership. Elasticsearch licenses this file to you under
|
|
|
|
* the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
* not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing,
|
|
|
|
* software distributed under the License is distributed on an
|
|
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
* KIND, either express or implied. See the License for the
|
|
|
|
* specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package org.elasticsearch.bootstrap;
|
|
|
|
|
2018-10-25 15:52:50 +02:00
|
|
|
import org.apache.logging.log4j.LogManager;
|
2016-08-09 13:34:23 -04:00
|
|
|
import org.apache.logging.log4j.Logger;
|
2019-11-22 14:58:17 +00:00
|
|
|
import org.elasticsearch.cli.Terminal;
|
2016-07-07 14:44:03 -04:00
|
|
|
import org.elasticsearch.common.SuppressForbidden;
|
|
|
|
|
|
|
|
import java.io.IOError;
|
2016-08-10 21:22:53 -04:00
|
|
|
import java.security.AccessController;
|
|
|
|
import java.security.PrivilegedAction;
|
2016-07-07 14:44:03 -04:00
|
|
|
|
|
|
|
class ElasticsearchUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
|
2018-10-25 15:52:50 +02:00
|
|
|
private static final Logger logger = LogManager.getLogger(ElasticsearchUncaughtExceptionHandler.class);
|
2016-07-07 14:44:03 -04:00
|
|
|
|
|
|
|
@Override
|
2019-11-22 14:58:17 +00:00
|
|
|
public void uncaughtException(Thread thread, Throwable t) {
|
|
|
|
if (isFatalUncaught(t)) {
|
2016-07-07 14:44:03 -04:00
|
|
|
try {
|
2019-11-22 14:58:17 +00:00
|
|
|
onFatalUncaught(thread.getName(), t);
|
2016-07-07 14:44:03 -04:00
|
|
|
} finally {
|
|
|
|
// we use specific error codes in case the above notification failed, at least we
|
|
|
|
// will have some indication of the error bringing us down
|
2019-11-22 14:58:17 +00:00
|
|
|
if (t instanceof InternalError) {
|
2016-07-07 14:44:03 -04:00
|
|
|
halt(128);
|
2019-11-22 14:58:17 +00:00
|
|
|
} else if (t instanceof OutOfMemoryError) {
|
2016-07-07 14:44:03 -04:00
|
|
|
halt(127);
|
2019-11-22 14:58:17 +00:00
|
|
|
} else if (t instanceof StackOverflowError) {
|
2016-07-07 14:44:03 -04:00
|
|
|
halt(126);
|
2019-11-22 14:58:17 +00:00
|
|
|
} else if (t instanceof UnknownError) {
|
2016-07-07 14:44:03 -04:00
|
|
|
halt(125);
|
2019-11-22 14:58:17 +00:00
|
|
|
} else if (t instanceof IOError) {
|
2016-07-07 14:44:03 -04:00
|
|
|
halt(124);
|
|
|
|
} else {
|
|
|
|
halt(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2019-11-22 14:58:17 +00:00
|
|
|
onNonFatalUncaught(thread.getName(), t);
|
2016-07-07 14:44:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean isFatalUncaught(Throwable e) {
|
2017-11-06 17:55:11 -05:00
|
|
|
return e instanceof Error;
|
2016-07-07 14:44:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void onFatalUncaught(final String threadName, final Throwable t) {
|
2019-11-22 14:58:17 +00:00
|
|
|
final String message = "fatal error in thread [" + threadName + "], exiting";
|
|
|
|
logger.error(message, t);
|
|
|
|
Terminal.DEFAULT.errorPrintln(message);
|
|
|
|
t.printStackTrace(Terminal.DEFAULT.getErrorWriter());
|
|
|
|
// Without a final flush, the stacktrace may not be shown before ES exits
|
|
|
|
Terminal.DEFAULT.flush();
|
2016-07-07 14:44:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void onNonFatalUncaught(final String threadName, final Throwable t) {
|
2019-11-22 14:58:17 +00:00
|
|
|
final String message = "uncaught exception in thread [" + threadName + "]";
|
|
|
|
logger.error(message, t);
|
|
|
|
Terminal.DEFAULT.errorPrintln(message);
|
|
|
|
t.printStackTrace(Terminal.DEFAULT.getErrorWriter());
|
|
|
|
// Without a final flush, the stacktrace may not be shown if ES goes on to exit
|
|
|
|
Terminal.DEFAULT.flush();
|
2016-07-07 14:44:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void halt(int status) {
|
2017-11-24 19:00:18 -05:00
|
|
|
AccessController.doPrivileged(new PrivilegedHaltAction(status));
|
|
|
|
}
|
|
|
|
|
|
|
|
static class PrivilegedHaltAction implements PrivilegedAction<Void> {
|
|
|
|
|
|
|
|
private final int status;
|
|
|
|
|
|
|
|
private PrivilegedHaltAction(final int status) {
|
|
|
|
this.status = status;
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressForbidden(reason = "halt")
|
|
|
|
@Override
|
|
|
|
public Void run() {
|
|
|
|
// we halt to prevent shutdown hooks from running
|
|
|
|
Runtime.getRuntime().halt(status);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2016-07-07 14:44:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|