Modify logging system

This commit is contained in:
huangyuhui 2017-02-26 20:21:35 +08:00
parent 0dfd8af7d5
commit 7436736040
10 changed files with 83 additions and 105 deletions

View File

@ -53,13 +53,12 @@ import org.jackhuang.hmcl.util.log.layout.DefaultLayout;
import org.jackhuang.hmcl.util.ui.MyRepaintManager; import org.jackhuang.hmcl.util.ui.MyRepaintManager;
import org.jackhuang.hmcl.util.upgrade.IUpgrader; import org.jackhuang.hmcl.util.upgrade.IUpgrader;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
import org.jackhuang.hmcl.util.sys.JavaProcess;
/** /**
* *
* @author huangyuhui * @author huangyuhui
*/ */
public final class Main implements Runnable { public final class Main {
private static final X509TrustManager XTM = new X509TrustManager() { private static final X509TrustManager XTM = new X509TrustManager() {
@Override @Override
@ -192,7 +191,6 @@ public final class Main implements Runnable {
} }
LogWindow.INSTANCE.clean(); LogWindow.INSTANCE.clean();
LogWindow.INSTANCE.setTerminateGame(new Main()::run);
Settings.UPDATE_CHECKER.upgrade.register(IUpgrader.NOW_UPGRADER); Settings.UPDATE_CHECKER.upgrade.register(IUpgrader.NOW_UPGRADER);
Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute(); Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute();
@ -214,12 +212,6 @@ public final class Main implements Runnable {
} }
} }
@Override
public void run() {
for (Process p : JavaProcess.processes)
p.destroy();
}
public static void invokeUpdate() { public static void invokeUpdate() {
MainFrame.INSTANCE.invokeUpdate(); MainFrame.INSTANCE.invokeUpdate();
} }

View File

@ -20,6 +20,7 @@ package org.jackhuang.hmcl.ui;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.jackhuang.hmcl.api.HMCLApi; import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent; import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent; import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
@ -40,7 +41,6 @@ import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.DefaultPlugin; import org.jackhuang.hmcl.util.DefaultPlugin;
import org.jackhuang.hmcl.util.sys.FileUtils; import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.sys.ProcessMonitor; import org.jackhuang.hmcl.util.sys.ProcessMonitor;
import org.jackhuang.hmcl.util.net.WebFrame;
/** /**
* *
@ -89,29 +89,22 @@ public class LaunchingUIDaemon {
break; break;
} }
} }
if (!LogWindow.INSTANCE.isVisible()) { String msg = C.i18n("launch.exited_abnormally") + " exit code: " + exitCode;
String msg = C.i18n("launch.exited_abnormally") + " exit code: " + exitCode; if (errorText != null)
if (errorText != null) msg += ", advice: " + MinecraftCrashAdvicer.getAdvice(FileUtils.readQuietly(new File(errorText)));
msg += ", advice: " + MinecraftCrashAdvicer.getAdvice(FileUtils.readQuietly(new File(errorText))); HMCLog.err(msg);
WebFrame f = new WebFrame(logs); SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.setVisible(true));
f.setModal(true); noExitThisTime = true;
f.setTitle(msg);
f.setVisible(true);
}
checkExit((LauncherVisibility) ((ProcessMonitor) event.getSource()).getTag());
}); });
HMCLApi.EVENT_BUS.channel(JVMLaunchFailedEvent.class).register(event -> { HMCLApi.EVENT_BUS.channel(JVMLaunchFailedEvent.class).register(event -> {
int exitCode = event.getValue().getExitCode(); int exitCode = event.getValue().getExitCode();
HMCLog.err("Cannot create jvm, exit code: " + exitCode); HMCLog.err("Cannot create jvm, exit code: " + exitCode);
if (!LogWindow.INSTANCE.isVisible()) { SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.setVisible(true));
WebFrame f = new WebFrame(event.getValue().getStdOutLines().toArray(new String[0])); noExitThisTime = true;
f.setModal(true);
f.setTitle(C.i18n("launch.cannot_create_jvm") + " exit code: " + exitCode);
f.setVisible(true);
}
checkExit((LauncherVisibility) ((ProcessMonitor) event.getSource()).getTag());
}); });
} }
boolean noExitThisTime = false;
void runGame(Profile profile) { void runGame(Profile profile) {
MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching")); MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching"));
@ -168,12 +161,14 @@ public class LaunchingUIDaemon {
} }
}; };
private static void checkExit(LauncherVisibility v) { private void checkExit(LauncherVisibility v) {
if (v != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible()) { if (v != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible() && !noExitThisTime) {
HMCLog.log("Launcher will exit now."); HMCLog.log("Launcher will exit now.");
System.exit(0); System.exit(0);
} else } else {
HMCLog.log("Launcher will not exit now."); HMCLog.log("Launcher will not exit now.");
noExitThisTime = false;
}
} }
private static final Consumer<LaunchSucceededEvent> LAUNCH_SCRIPT_FINISHER = event -> { private static final Consumer<LaunchSucceededEvent> LAUNCH_SCRIPT_FINISHER = event -> {

View File

@ -32,7 +32,7 @@
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
<Component id="jScrollPane2" max="32767" attributes="0"/> <Component id="pnlLog" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<Component id="btnTieBa" min="-2" max="-2" attributes="0"/> <Component id="btnTieBa" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
@ -62,7 +62,7 @@
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="lblCrash" min="-2" max="-2" attributes="0"/> <Component id="lblCrash" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane2" pref="356" max="32767" attributes="0"/> <Component id="pnlLog" pref="356" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="btnClear" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="btnClear" alignment="3" min="-2" max="-2" attributes="0"/>
@ -161,7 +161,7 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnGitHubActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnGitHubActionPerformed"/>
</Events> </Events>
</Component> </Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane2"> <Container class="javax.swing.JScrollPane" name="pnlLog">
<AuxValues> <AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues> </AuxValues>

View File

@ -18,6 +18,7 @@
package org.jackhuang.hmcl.ui; package org.jackhuang.hmcl.ui;
import java.io.PrintStream; import java.io.PrintStream;
import javax.swing.JScrollBar;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.text.Document; import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet; import javax.swing.text.SimpleAttributeSet;
@ -28,6 +29,7 @@ import org.jackhuang.hmcl.util.log.Level;
import org.jackhuang.hmcl.api.func.NonFunction; import org.jackhuang.hmcl.api.func.NonFunction;
import org.jackhuang.hmcl.util.DoubleOutputStream; import org.jackhuang.hmcl.util.DoubleOutputStream;
import org.jackhuang.hmcl.util.Utils; import org.jackhuang.hmcl.util.Utils;
import org.jackhuang.hmcl.util.sys.ProcessMonitor;
import org.jackhuang.hmcl.util.ui.SwingUtils; import org.jackhuang.hmcl.util.ui.SwingUtils;
/** /**
@ -36,9 +38,7 @@ import org.jackhuang.hmcl.util.ui.SwingUtils;
*/ */
public class LogWindow extends javax.swing.JFrame { public class LogWindow extends javax.swing.JFrame {
boolean movingEnd;
NonFunction<Boolean> listener; NonFunction<Boolean> listener;
Runnable terminateGameListener;
/** /**
* Creates new form LogWindow * Creates new form LogWindow
@ -46,8 +46,6 @@ public class LogWindow extends javax.swing.JFrame {
public LogWindow() { public LogWindow() {
initComponents(); initComponents();
movingEnd = true;
DoubleOutputStream out = new DoubleOutputStream(new LogWindowOutputStream(this, Level.INFO), System.out); DoubleOutputStream out = new DoubleOutputStream(new LogWindowOutputStream(this, Level.INFO), System.out);
System.setOut(new PrintStream(out)); System.setOut(new PrintStream(out));
DoubleOutputStream err = new DoubleOutputStream(new LogWindowOutputStream(this, Level.ERROR), System.err); DoubleOutputStream err = new DoubleOutputStream(new LogWindowOutputStream(this, Level.ERROR), System.err);
@ -79,7 +77,7 @@ public class LogWindow extends javax.swing.JFrame {
btnMCF = new javax.swing.JButton(); btnMCF = new javax.swing.JButton();
btnTerminateGame = new javax.swing.JButton(); btnTerminateGame = new javax.swing.JButton();
btnGitHub = new javax.swing.JButton(); btnGitHub = new javax.swing.JButton();
jScrollPane2 = new javax.swing.JScrollPane(); pnlLog = new javax.swing.JScrollPane();
txtLog = new javax.swing.JTextPane(); txtLog = new javax.swing.JTextPane();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
@ -148,7 +146,7 @@ public class LogWindow extends javax.swing.JFrame {
} }
}); });
jScrollPane2.setViewportView(txtLog); pnlLog.setViewportView(txtLog);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
@ -157,7 +155,7 @@ public class LogWindow extends javax.swing.JFrame {
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jScrollPane2) .addComponent(pnlLog)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(btnTieBa) .addComponent(btnTieBa)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -183,7 +181,7 @@ public class LogWindow extends javax.swing.JFrame {
.addContainerGap() .addContainerGap()
.addComponent(lblCrash) .addComponent(lblCrash)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE) .addComponent(pnlLog, javax.swing.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnClear) .addComponent(btnClear)
@ -201,8 +199,8 @@ public class LogWindow extends javax.swing.JFrame {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed
if (listener != null && listener.apply() && terminateGameListener != null) if (listener != null && listener.apply())
terminateGameListener.run(); terminateGames();
SwingUtils.exitIfNoWindow(this, true); SwingUtils.exitIfNoWindow(this, true);
}//GEN-LAST:event_btnCloseActionPerformed }//GEN-LAST:event_btnCloseActionPerformed
@ -227,8 +225,7 @@ public class LogWindow extends javax.swing.JFrame {
}//GEN-LAST:event_btnMCFActionPerformed }//GEN-LAST:event_btnMCFActionPerformed
private void btnTerminateGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTerminateGameActionPerformed private void btnTerminateGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTerminateGameActionPerformed
if (terminateGameListener != null) terminateGames();
terminateGameListener.run();
}//GEN-LAST:event_btnTerminateGameActionPerformed }//GEN-LAST:event_btnTerminateGameActionPerformed
private void btnGitHubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGitHubActionPerformed private void btnGitHubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGitHubActionPerformed
@ -236,11 +233,15 @@ public class LogWindow extends javax.swing.JFrame {
}//GEN-LAST:event_btnGitHubActionPerformed }//GEN-LAST:event_btnGitHubActionPerformed
private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
if (listener != null && listener.apply() && terminateGameListener != null) if (listener != null && listener.apply())
terminateGameListener.run(); terminateGames();
SwingUtils.exitIfNoWindow(this); SwingUtils.exitIfNoWindow(this);
}//GEN-LAST:event_formWindowClosing }//GEN-LAST:event_formWindowClosing
void terminateGames() {
ProcessMonitor.stopAll();
}
public void log(final String status, final Level c) { public void log(final String status, final Level c) {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
String newStatus = status.replace("\t", " "); String newStatus = status.replace("\t", " ");
@ -252,11 +253,6 @@ public class LogWindow extends javax.swing.JFrame {
} catch (Exception ex) { } catch (Exception ex) {
HMCLog.err("Failed to insert \"" + newStatus + "\" to " + d.getLength(), ex); HMCLog.err("Failed to insert \"" + newStatus + "\" to " + d.getLength(), ex);
} }
if (movingEnd) {
int position = d.getLength();
txtLog.setCaretPosition(position);
}
}); });
} }
@ -264,22 +260,10 @@ public class LogWindow extends javax.swing.JFrame {
this.listener = exit; this.listener = exit;
} }
public void setTerminateGame(Runnable l) {
this.terminateGameListener = l;
}
public void clean() { public void clean() {
txtLog.setText(""); txtLog.setText("");
} }
public boolean getMovingEnd() {
return movingEnd;
}
public void setMovingEnd(boolean b) {
movingEnd = b;
}
@Override @Override
public void setVisible(boolean b) { public void setVisible(boolean b) {
lblCrash.setVisible(false); lblCrash.setVisible(false);
@ -316,8 +300,8 @@ public class LogWindow extends javax.swing.JFrame {
private javax.swing.JButton btnMCF; private javax.swing.JButton btnMCF;
private javax.swing.JButton btnTerminateGame; private javax.swing.JButton btnTerminateGame;
private javax.swing.JButton btnTieBa; private javax.swing.JButton btnTieBa;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JLabel lblCrash; private javax.swing.JLabel lblCrash;
private javax.swing.JScrollPane pnlLog;
private javax.swing.JTextPane txtLog; private javax.swing.JTextPane txtLog;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
} }

View File

@ -20,7 +20,6 @@ package org.jackhuang.hmcl.ui;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Objects; import java.util.Objects;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import org.jackhuang.hmcl.util.code.Charsets;
import org.jackhuang.hmcl.util.log.Level; import org.jackhuang.hmcl.util.log.Level;
/** /**

View File

@ -167,7 +167,7 @@ public abstract class GameLauncher {
ProcessBuilder builder = new ProcessBuilder(str); ProcessBuilder builder = new ProcessBuilder(str);
if (options.getLaunchVersion() == null || service.baseDirectory() == null) if (options.getLaunchVersion() == null || service.baseDirectory() == null)
throw new Error("Fucking bug!"); throw new Error("Fucking bug!");
builder.redirectErrorStream(true).directory(service.version().getRunDirectory(options.getLaunchVersion())) builder.directory(service.version().getRunDirectory(options.getLaunchVersion()))
.environment().put("APPDATA", service.baseDirectory().getAbsolutePath()); .environment().put("APPDATA", service.baseDirectory().getAbsolutePath());
JavaProcess jp = new JavaProcess(str, builder.start()); JavaProcess jp = new JavaProcess(str, builder.start());
HMCLog.log("Have started the process"); HMCLog.log("Have started the process");

View File

@ -50,7 +50,8 @@ public enum Level {
public static final Pattern MINECRAFT_LOGGER = Pattern.compile("\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]"); public static final Pattern MINECRAFT_LOGGER = Pattern.compile("\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]");
public static final String JAVA_SYMBOL = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*"; public static final String JAVA_SYMBOL = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*";
public static Level guessLevel(String line, Level level) { public static Level guessLevel(String line, Level preLevel) {
Level level = preLevel;
Matcher m = MINECRAFT_LOGGER.matcher(line); Matcher m = MINECRAFT_LOGGER.matcher(line);
if (m.find()) { if (m.find()) {
// New style logs from log4j // New style logs from log4j
@ -98,7 +99,7 @@ public enum Level {
|| line.matches("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$]?[a-zA-Z\\d_$]*(Exception|Error|Throwable)") || line.matches("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$]?[a-zA-Z\\d_$]*(Exception|Error|Throwable)")
|| line.matches("... \\d+ more$")) || line.matches("... \\d+ more$"))
return ERROR; return ERROR;
return level; return preLevel.level < level.level ? preLevel : level;
} }
} }

View File

@ -20,7 +20,6 @@ package org.jackhuang.hmcl.util.sys;
import org.jackhuang.hmcl.api.IProcess; import org.jackhuang.hmcl.api.IProcess;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
/** /**
@ -28,7 +27,6 @@ import java.util.List;
* @author huangyuhui * @author huangyuhui
*/ */
public class JavaProcess implements IProcess { public class JavaProcess implements IProcess {
public static HashSet<Process> processes = new HashSet<>();
private final List<String> commands; private final List<String> commands;
private final Process process; private final Process process;
@ -37,7 +35,6 @@ public class JavaProcess implements IProcess {
public JavaProcess(List<String> commands, Process process) { public JavaProcess(List<String> commands, Process process) {
this.commands = commands; this.commands = commands;
this.process = process; this.process = process;
processes.add(process);
} }
public JavaProcess(String[] commands, Process process) { public JavaProcess(String[] commands, Process process) {

View File

@ -19,7 +19,6 @@ package org.jackhuang.hmcl.util.sys;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import org.jackhuang.hmcl.util.CollectionUtils;
import org.jackhuang.hmcl.api.HMCLApi; import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent; import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent; import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
@ -36,7 +35,9 @@ import org.jackhuang.hmcl.api.IProcess;
*/ */
public class ProcessMonitor { public class ProcessMonitor {
private final HashSet<Thread> al = new HashSet<>(); public static final HashSet<ProcessMonitor> MONITORS = new HashSet<>();
ProcessThread inputThread, errorThread;
private final IProcess p; private final IProcess p;
public ProcessMonitor(IProcess p) { public ProcessMonitor(IProcess p) {
@ -46,7 +47,7 @@ public class ProcessMonitor {
public IProcess getProcess() { public IProcess getProcess() {
return p; return p;
} }
private Object tag; private Object tag;
public Object getTag() { public Object getTag() {
@ -56,36 +57,44 @@ public class ProcessMonitor {
public void setTag(Object tag) { public void setTag(Object tag) {
this.tag = tag; this.tag = tag;
} }
public void start() { public void start() {
MONITORS.add(this);
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStartingEvent(this, p)); HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStartingEvent(this, p));
ProcessThread a = new ProcessThread(p); inputThread = new ProcessThread(p, false);
a.stopEvent.register(event -> { errorThread = new ProcessThread(p, true);
HMCLog.log("Process exit code: " + p.getExitCode()); inputThread.stopEvent.register(this::threadStopped);
if (p.getExitCode() != 0 || StrUtils.containsOne(p.getStdOutLines(), inputThread.stopEvent.register(event -> processThreadStopped((ProcessThread) event.getSource()));
Arrays.asList("Unable to launch"), errorThread.stopEvent.register(this::threadStopped);
x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR))) inputThread.start();
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(ProcessMonitor.this, p));
if (p.getExitCode() != 0 && StrUtils.containsOne(p.getStdOutLines(),
Arrays.asList("Could not create the Java Virtual Machine.",
"Error occurred during initialization of VM",
"A fatal exception has occurred. Program will exit.",
"Unable to launch"),
x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR)))
HMCLApi.EVENT_BUS.fireChannel(new JVMLaunchFailedEvent(ProcessMonitor.this, p));
processThreadStopped((ProcessThread) event.getSource(), false);
});
a.start();
al.add(a);
} }
void processThreadStopped(ProcessThread t1, boolean forceTermintate) { private void threadStopped() {
CollectionUtils.removeIf(al, t -> t == t1 || !t.isAlive()); HMCLog.log("Process exit code: " + p.getExitCode());
if (al.isEmpty() || forceTermintate) { if (p.getExitCode() != 0 || StrUtils.containsOne(p.getStdOutLines(),
for (Thread a : al) Arrays.asList("Unable to launch"),
a.interrupt(); x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR)))
al.clear(); HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(ProcessMonitor.this, p));
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStoppedEvent(this, p)); if (p.getExitCode() != 0 && StrUtils.containsOne(p.getStdOutLines(),
Arrays.asList("Could not create the Java Virtual Machine.",
"Error occurred during initialization of VM",
"A fatal exception has occurred. Program will exit.",
"Unable to launch"),
x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR)))
HMCLApi.EVENT_BUS.fireChannel(new JVMLaunchFailedEvent(ProcessMonitor.this, p));
}
private void processThreadStopped(ProcessThread t1) {
MONITORS.remove(this);
errorThread.interrupt();
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStoppedEvent(this, p));
}
public static void stopAll() {
for (ProcessMonitor monitor : MONITORS) {
monitor.getProcess().getRawProcess().destroy();
monitor.inputThread.interrupt();
monitor.errorThread.interrupt();
} }
} }
} }

View File

@ -34,12 +34,14 @@ import org.jackhuang.hmcl.api.IProcess;
public class ProcessThread extends Thread { public class ProcessThread extends Thread {
IProcess p; IProcess p;
boolean readError;
public final EventHandler<SimpleEvent<String>> printlnEvent = new EventHandler<>(); public final EventHandler<SimpleEvent<String>> printlnEvent = new EventHandler<>();
public final EventHandler<SimpleEvent<IProcess>> stopEvent = new EventHandler<>(); public final EventHandler<SimpleEvent<IProcess>> stopEvent = new EventHandler<>();
public ProcessThread(IProcess process) { public ProcessThread(IProcess process, boolean readError) {
p = process; p = process;
this.readError = readError;
setDaemon(readError);
} }
public IProcess getProcess() { public IProcess getProcess() {
@ -51,7 +53,7 @@ public class ProcessThread extends Thread {
setName("ProcessMonitor"); setName("ProcessMonitor");
BufferedReader br = null; BufferedReader br = null;
try { try {
InputStream in = p.getRawProcess().getInputStream(); InputStream in = readError ? p.getRawProcess().getErrorStream() : p.getRawProcess().getInputStream();
br = new BufferedReader(new InputStreamReader(in, Charsets.toCharset())); br = new BufferedReader(new InputStreamReader(in, Charsets.toCharset()));
String line; String line;
@ -66,7 +68,6 @@ public class ProcessThread extends Thread {
System.out.println("MC: " + line); System.out.println("MC: " + line);
p.getStdOutLines().add(line); p.getStdOutLines().add(line);
} }
JavaProcess.processes.remove(p.getRawProcess());
stopEvent.fire(new SimpleEvent<>(this, p)); stopEvent.fire(new SimpleEvent<>(this, p));
} catch (IOException e) { } catch (IOException e) {
HMCLog.err("An error occured when reading process stdout/stderr.", e); HMCLog.err("An error occured when reading process stdout/stderr.", e);