mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-02-11 16:59:54 +08:00
Ignoring IOExceptions in log4j handler
This commit is contained in:
parent
98b43945ed
commit
6823291eb0
@ -40,6 +40,7 @@ import org.jackhuang.hmcl.util.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public final class LauncherHelper {
|
||||
@ -282,6 +283,7 @@ public final class LauncherHelper {
|
||||
private boolean lwjgl;
|
||||
private LogWindow logWindow;
|
||||
private final LinkedList<Pair<String, Log4jLevel>> logs;
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
public HMCLProcessListener(AuthInfo authInfo, VersionSetting setting) {
|
||||
this.setting = setting;
|
||||
@ -307,11 +309,12 @@ public final class LauncherHelper {
|
||||
Platform.runLater(() -> {
|
||||
logWindow = new LogWindow();
|
||||
logWindow.show();
|
||||
latch.countDown();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLog(String log, Log4jLevel level) {
|
||||
public synchronized void onLog(String log, Log4jLevel level) {
|
||||
String newLog = log;
|
||||
for (Map.Entry<String, String> entry : forbiddenTokens.entrySet())
|
||||
newLog = newLog.replace(entry.getKey(), entry.getValue());
|
||||
@ -321,13 +324,19 @@ public final class LauncherHelper {
|
||||
else
|
||||
System.out.print(log);
|
||||
|
||||
Platform.runLater(() -> {
|
||||
logs.add(new Pair<>(log, level));
|
||||
if (logs.size() > Settings.INSTANCE.getLogLines())
|
||||
logs.removeFirst();
|
||||
if (logWindow != null)
|
||||
logWindow.logLine(log, level);
|
||||
});
|
||||
logs.add(new Pair<>(log, level));
|
||||
if (logs.size() > Settings.INSTANCE.getLogLines())
|
||||
logs.removeFirst();
|
||||
|
||||
if (setting.isShowLogs()) {
|
||||
Lang.invoke(() -> {
|
||||
latch.await();
|
||||
logWindow.waitForLoaded();
|
||||
});
|
||||
|
||||
Platform.runLater(() -> logWindow.logLine(log, level));
|
||||
}
|
||||
|
||||
|
||||
if (!lwjgl && log.contains("LWJGL Version: ")) {
|
||||
lwjgl = true;
|
||||
|
@ -116,9 +116,9 @@ public final class LogWindow extends Stage {
|
||||
}
|
||||
|
||||
public void logLine(String line, Log4jLevel level) {
|
||||
Element div = impl.engine.getDocument().createElement("div");
|
||||
Element div = impl.document.createElement("div");
|
||||
// a <pre> element to prevent multiple spaces and tabs being removed.
|
||||
Element pre = impl.engine.getDocument().createElement("pre");
|
||||
Element pre = impl.document.createElement("pre");
|
||||
pre.setTextContent(line);
|
||||
div.appendChild(pre);
|
||||
impl.body.appendChild(div);
|
||||
@ -143,6 +143,10 @@ public final class LogWindow extends Stage {
|
||||
}
|
||||
}
|
||||
|
||||
public void waitForLoaded() throws InterruptedException {
|
||||
latch.await();
|
||||
}
|
||||
|
||||
public class LogWindowImpl extends StackPane {
|
||||
|
||||
@FXML
|
||||
|
@ -36,6 +36,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
|
||||
|
||||
private static final HashMap<String, String> SOURCE = new HashMap<String, String>() {
|
||||
{
|
||||
put("javafx.fxml.LoadException", Main.i18n("crash.NoClassDefFound"));
|
||||
put("UnsatisfiedLinkError", Main.i18n("crash.user_fault"));
|
||||
put("java.lang.NoClassDefFoundError", Main.i18n("crash.NoClassDefFound"));
|
||||
put("java.lang.VerifyError", Main.i18n("crash.NoClassDefFound"));
|
||||
@ -68,10 +69,14 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
String s = StringUtils.getStackTrace(e);
|
||||
if (!s.contains("org.jackhuang"))
|
||||
String stackTrace = StringUtils.getStackTrace(e);
|
||||
if (!stackTrace.contains("org.jackhuang"))
|
||||
return;
|
||||
|
||||
if (THROWABLE_SET.contains(stackTrace))
|
||||
return;
|
||||
THROWABLE_SET.add(stackTrace);
|
||||
|
||||
try {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("---- Hello Minecraft! Crash Report ----\n");
|
||||
@ -79,7 +84,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
|
||||
builder.append(" Time: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append("\n");
|
||||
builder.append(" Thread: ").append(t.toString()).append("\n");
|
||||
builder.append("\n Content: \n ");
|
||||
builder.append(s).append("\n\n");
|
||||
builder.append(stackTrace).append("\n\n");
|
||||
builder.append("-- System Details --\n");
|
||||
builder.append(" Operating System: ").append(System.getProperty("os.name")).append(' ').append(OperatingSystem.SYSTEM_VERSION).append("\n");
|
||||
builder.append(" Java Version: ").append(System.getProperty("java.version")).append(", ").append(System.getProperty("java.vendor")).append("\n");
|
||||
@ -91,7 +96,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
|
||||
if (checkThrowable(e) && !text.contains("OpenJDK")) {
|
||||
Platform.runLater(() -> new CrashWindow(text).show());
|
||||
if (!Main.UPDATE_CHECKER.isOutOfDate())
|
||||
reportToServer(text, s);
|
||||
reportToServer(text);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Logging.LOG.log(Level.SEVERE, "Unable to caught exception", ex);
|
||||
@ -101,10 +106,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
|
||||
|
||||
private static final HashSet<String> THROWABLE_SET = new HashSet<>();
|
||||
|
||||
private void reportToServer(final String text, String stacktrace) {
|
||||
if (THROWABLE_SET.contains(stacktrace) || stacktrace.contains("Font") || stacktrace.contains("InternalError"))
|
||||
return;
|
||||
THROWABLE_SET.add(stacktrace);
|
||||
private void reportToServer(final String text) {
|
||||
Thread t = new Thread(() -> {
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put("crash_report", text);
|
||||
|
@ -18,10 +18,7 @@
|
||||
package org.jackhuang.hmcl.launch;
|
||||
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.util.Constants;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.Log4jLevel;
|
||||
import org.jackhuang.hmcl.util.OperatingSystem;
|
||||
import org.jackhuang.hmcl.util.*;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
@ -34,10 +31,15 @@ import java.io.InterruptedIOException;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* This class is to parse log4j classic XML layout logging,
|
||||
@ -54,6 +56,7 @@ final class Log4jHandler extends Thread {
|
||||
private final PipedOutputStream outputStream = new PipedOutputStream();
|
||||
private final PipedInputStream inputStream = Lang.invoke(() -> new PipedInputStream(outputStream));
|
||||
private final AtomicBoolean interrupted = new AtomicBoolean(false);
|
||||
private final List<String> logs = new LinkedList<>();
|
||||
|
||||
public Log4jHandler(BiConsumer<String, Log4jLevel> callback) {
|
||||
this.callback = callback;
|
||||
@ -73,7 +76,7 @@ final class Log4jHandler extends Thread {
|
||||
// Game has been interrupted.
|
||||
interrupted.set(true);
|
||||
} catch (SAXException | IOException e) {
|
||||
Lang.throwable(e);
|
||||
Logging.LOG.log(Level.WARNING, "An error occurred when reading console lines", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +86,7 @@ final class Log4jHandler extends Thread {
|
||||
|
||||
Lang.invoke(() -> Schedulers.newThread().schedule(() -> {
|
||||
if (!interrupted.get()) {
|
||||
Lang.invoke(() -> newLine("</output>").get());
|
||||
newLine("</output>").get();
|
||||
outputStream.close();
|
||||
join();
|
||||
}
|
||||
@ -92,13 +95,22 @@ final class Log4jHandler extends Thread {
|
||||
|
||||
public Future<?> newLine(String log) {
|
||||
return Schedulers.computation().schedule(() -> {
|
||||
byte[] bytes = (log + OperatingSystem.LINE_SEPARATOR)
|
||||
.replace("log4j:Event", "log4j_Event")
|
||||
.replace("log4j:Message", "log4j_Message")
|
||||
.replace("log4j:Throwable", "log4j_Throwable")
|
||||
.getBytes();
|
||||
outputStream.write(bytes);
|
||||
outputStream.flush();
|
||||
try {
|
||||
String line = (log + OperatingSystem.LINE_SEPARATOR)
|
||||
.replace("<![CDATA[", "")
|
||||
.replace("]]>", "")
|
||||
.replace("log4j:Event", "log4j_Event")
|
||||
.replace("<log4j:Message>", "<log4j_Message><![CDATA[")
|
||||
.replace("</log4j:Message>", "]]></log4j_Message>")
|
||||
.replace("log4j:Throwable", "log4j_Throwable");
|
||||
logs.add(line);
|
||||
byte[] bytes = line.getBytes(Charsets.UTF_8);
|
||||
outputStream.write(bytes);
|
||||
outputStream.flush();
|
||||
} catch (IOException e) {
|
||||
// Ignoring IOException, including read end dead.
|
||||
Logging.LOG.log(Level.WARNING, "An error occurred when writing console lines", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ public final class Lang {
|
||||
return function.apply(t);
|
||||
} catch (Exception e) {
|
||||
throwable(e);
|
||||
return null; // won't get to here.
|
||||
throw new Error(); // won't get to here.
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ public final class Lang {
|
||||
return supplier.get();
|
||||
} catch (Exception e) {
|
||||
throwable(e);
|
||||
return null; // won't get to here.
|
||||
throw new Error(); // won't get to here.
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user