Skip to content

Commit 49ea53b

Browse files
committed
Don't close stderr, print logs dir on fatal err
Closes elastic#46900. When running ES with --quiet, if ES then exits abnormally, a user has to go hunting in the logs for the error. Instead, never close System.err, and print more information to it if ES encounters a fatal error e.g. config validation, or some fatal runtime exception.
1 parent 5c23d29 commit 49ea53b

File tree

5 files changed

+37
-22
lines changed

5 files changed

+37
-22
lines changed

libs/cli/src/main/java/org/elasticsearch/cli/Terminal.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ public final boolean promptYesNo(String prompt, boolean defaultYes) {
151151
}
152152
}
153153

154+
public void flush() {
155+
this.getErrorWriter().flush();
156+
}
157+
154158
private static class ConsoleTerminal extends Terminal {
155159

156160
private static final Console CONSOLE = System.console();

server/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -346,10 +346,6 @@ static void init(
346346
}
347347

348348
INSTANCE.start();
349-
350-
if (closeStandardStreams) {
351-
closeSysError();
352-
}
353349
} catch (NodeValidationException | RuntimeException e) {
354350
// disable console logging, so user does not see the exception twice (jvm will show it already)
355351
final Logger rootLogger = LogManager.getRootLogger();
@@ -397,11 +393,6 @@ private static void closeSystOut() {
397393
System.out.close();
398394
}
399395

400-
@SuppressForbidden(reason = "System#err")
401-
private static void closeSysError() {
402-
System.err.close();
403-
}
404-
405396
private static void checkLucene() {
406397
if (Version.CURRENT.luceneVersion.equals(org.apache.lucene.util.Version.LATEST) == false) {
407398
throw new AssertionError("Lucene version mismatch this version of Elasticsearch requires lucene version ["

server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ public void checkPermission(Permission perm) {
9191
final Elasticsearch elasticsearch = new Elasticsearch();
9292
int status = main(args, elasticsearch, Terminal.DEFAULT);
9393
if (status != ExitCodes.OK) {
94+
Terminal.DEFAULT.errorPrintln("ERROR: Elasticsearch did not exit normally - check the logs at " +
95+
System.getProperty("es.logs.base_path") +
96+
System.getProperty("file.separator") +
97+
System.getProperty("es.logs.cluster_name") +
98+
".log"
99+
);
94100
exit(status);
95101
}
96102
}

server/src/main/java/org/elasticsearch/bootstrap/ElasticsearchUncaughtExceptionHandler.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
import org.apache.logging.log4j.LogManager;
2323
import org.apache.logging.log4j.Logger;
24-
import org.apache.logging.log4j.message.ParameterizedMessage;
24+
import org.elasticsearch.cli.Terminal;
2525
import org.elasticsearch.common.SuppressForbidden;
2626

2727
import java.io.IOError;
@@ -32,29 +32,29 @@ class ElasticsearchUncaughtExceptionHandler implements Thread.UncaughtExceptionH
3232
private static final Logger logger = LogManager.getLogger(ElasticsearchUncaughtExceptionHandler.class);
3333

3434
@Override
35-
public void uncaughtException(Thread t, Throwable e) {
36-
if (isFatalUncaught(e)) {
35+
public void uncaughtException(Thread thread, Throwable t) {
36+
if (isFatalUncaught(t)) {
3737
try {
38-
onFatalUncaught(t.getName(), e);
38+
onFatalUncaught(thread.getName(), t);
3939
} finally {
4040
// we use specific error codes in case the above notification failed, at least we
4141
// will have some indication of the error bringing us down
42-
if (e instanceof InternalError) {
42+
if (t instanceof InternalError) {
4343
halt(128);
44-
} else if (e instanceof OutOfMemoryError) {
44+
} else if (t instanceof OutOfMemoryError) {
4545
halt(127);
46-
} else if (e instanceof StackOverflowError) {
46+
} else if (t instanceof StackOverflowError) {
4747
halt(126);
48-
} else if (e instanceof UnknownError) {
48+
} else if (t instanceof UnknownError) {
4949
halt(125);
50-
} else if (e instanceof IOError) {
50+
} else if (t instanceof IOError) {
5151
halt(124);
5252
} else {
5353
halt(1);
5454
}
5555
}
5656
} else {
57-
onNonFatalUncaught(t.getName(), e);
57+
onNonFatalUncaught(thread.getName(), t);
5858
}
5959
}
6060

@@ -63,11 +63,21 @@ static boolean isFatalUncaught(Throwable e) {
6363
}
6464

6565
void onFatalUncaught(final String threadName, final Throwable t) {
66-
logger.error(() -> new ParameterizedMessage("fatal error in thread [{}], exiting", threadName), t);
66+
final String message = "fatal error in thread [" + threadName + "], exiting";
67+
logger.error(message, t);
68+
Terminal.DEFAULT.errorPrintln(message);
69+
t.printStackTrace(Terminal.DEFAULT.getErrorWriter());
70+
// Without a final flush, the stacktrace may not be shown before ES exits
71+
Terminal.DEFAULT.flush();
6772
}
6873

6974
void onNonFatalUncaught(final String threadName, final Throwable t) {
70-
logger.warn(() -> new ParameterizedMessage("uncaught exception in thread [{}]", threadName), t);
75+
final String message = "uncaught exception in thread [" + threadName + "]";
76+
logger.error(message, t);
77+
Terminal.DEFAULT.errorPrintln(message);
78+
t.printStackTrace(Terminal.DEFAULT.getErrorWriter());
79+
// Without a final flush, the stacktrace may not be shown if ES goes on to exit
80+
Terminal.DEFAULT.flush();
7181
}
7282

7383
void halt(int status) {

server/src/main/java/org/elasticsearch/bootstrap/StartupException.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,11 @@ private void printStackTrace(Consumer<String> consumer) {
111111
// if its a guice exception, the whole thing really will not be in the log, its megabytes.
112112
// refer to the hack in bootstrap, where we don't log it
113113
if (originalCause instanceof CreationException == false) {
114-
consumer.accept("Refer to the log for complete error details.");
114+
final String logPath = System.getProperty("es.logs.base_path") +
115+
System.getProperty("file.separator") +
116+
System.getProperty("es.logs.cluster_name") +
117+
".log";
118+
consumer.accept("For complete error details, refer to the log at " + logPath);
115119
}
116120
}
117121

0 commit comments

Comments
 (0)