Try to fix concurrentModificationException

This commit is contained in:
huangyuhui 2017-03-10 19:38:51 +08:00
parent 0f390e63d3
commit fd2a5a07a1
5 changed files with 43 additions and 9 deletions

View File

@ -82,6 +82,7 @@ public class LaunchingUIDaemon {
HMCLApi.EVENT_BUS.channel(JavaProcessStoppedEvent.class).register(event -> checkExit((LauncherVisibility) ((ProcessMonitor) event.getSource()).getTag())); HMCLApi.EVENT_BUS.channel(JavaProcessStoppedEvent.class).register(event -> checkExit((LauncherVisibility) ((ProcessMonitor) event.getSource()).getTag()));
HMCLApi.EVENT_BUS.channel(JavaProcessExitedAbnormallyEvent.class).register(event -> { HMCLApi.EVENT_BUS.channel(JavaProcessExitedAbnormallyEvent.class).register(event -> {
int exitCode = event.getValue().getExitCode(); int exitCode = event.getValue().getExitCode();
event.getValue().waitForCommandLineCompletion();
HMCLog.err("The game exited abnormally, exit code: " + exitCode); HMCLog.err("The game exited abnormally, exit code: " + exitCode);
String[] logs = event.getValue().getStdOutLines().toArray(new String[0]); String[] logs = event.getValue().getStdOutLines().toArray(new String[0]);
String errorText = null; String errorText = null;

View File

@ -17,7 +17,6 @@
*/ */
package org.jackhuang.hmcl.api; package org.jackhuang.hmcl.api;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -34,10 +33,12 @@ public interface IProcess {
List<String> getStartupCommands(); List<String> getStartupCommands();
ArrayList<String> getStdOutLines(); List<String> getStdOutLines();
boolean isRunning(); boolean isRunning();
void stop(); void stop();
void waitForCommandLineCompletion();
} }

View File

@ -18,9 +18,11 @@
package org.jackhuang.hmcl.util.sys; 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.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import org.jackhuang.hmcl.api.HMCLog;
/** /**
* *
@ -28,9 +30,10 @@ import java.util.List;
*/ */
public class JavaProcess implements IProcess { public class JavaProcess implements IProcess {
private final CountDownLatch latch = new CountDownLatch(2);
private final List<String> commands; private final List<String> commands;
private final Process process; private final Process process;
private final ArrayList<String> stdOutLines = new ArrayList<>(); private final Vector<String> stdOutLines = new Vector<>();
public JavaProcess(List<String> commands, Process process) { public JavaProcess(List<String> commands, Process process) {
this.commands = commands; this.commands = commands;
@ -57,7 +60,7 @@ public class JavaProcess implements IProcess {
} }
@Override @Override
public ArrayList<String> getStdOutLines() { public List<String> getStdOutLines() {
return this.stdOutLines; return this.stdOutLines;
} }
@ -72,6 +75,19 @@ public class JavaProcess implements IProcess {
return false; return false;
} }
CountDownLatch getLatch() {
return latch;
}
@Override
public void waitForCommandLineCompletion() {
try {
latch.await();
} catch (InterruptedException ignore) {
HMCLog.warn("Thread has been interrupted.", ignore);
}
}
@Override @Override
public int getExitCode() { public int getExitCode() {
try { try {

View File

@ -77,13 +77,14 @@ public class ProcessMonitor {
errorThread.start(); errorThread.start();
} }
private void threadStopped() { private void threadStopped(SimpleEvent<IProcess> event) {
ProcessThread t = (ProcessThread) event.getSource();
HMCLog.log("Process exit code: " + p.getExitCode()); HMCLog.log("Process exit code: " + p.getExitCode());
if (p.getExitCode() != 0 || StrUtils.containsOne(p.getStdOutLines(), if (p.getExitCode() != 0 || StrUtils.containsOne(t.getLines(),
Arrays.asList("Unable to launch"), Arrays.asList("Unable to launch"),
x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR))) x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR)))
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(ProcessMonitor.this, p)); HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(ProcessMonitor.this, p));
if (p.getExitCode() != 0 && StrUtils.containsOne(p.getStdOutLines(), if (p.getExitCode() != 0 && StrUtils.containsOne(t.getLines(),
Arrays.asList("Could not create the Java Virtual Machine.", Arrays.asList("Could not create the Java Virtual Machine.",
"Error occurred during initialization of VM", "Error occurred during initialization of VM",
"A fatal exception has occurred. Program will exit.", "A fatal exception has occurred. Program will exit.",

View File

@ -21,6 +21,8 @@ import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.List;
import java.util.Vector;
import org.jackhuang.hmcl.api.HMCLog; import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.api.event.EventHandler; import org.jackhuang.hmcl.api.event.EventHandler;
import org.jackhuang.hmcl.api.event.SimpleEvent; import org.jackhuang.hmcl.api.event.SimpleEvent;
@ -28,11 +30,13 @@ import org.jackhuang.hmcl.util.code.Charsets;
import org.jackhuang.hmcl.api.IProcess; import org.jackhuang.hmcl.api.IProcess;
/** /**
* Watch the process command line output(stdout or stderr).
* *
* @author huangyuhui * @author huangyuhui
*/ */
public class ProcessThread extends Thread { public class ProcessThread extends Thread {
Vector<String> lines = new Vector<>();
ProcessMonitor monitor; ProcessMonitor monitor;
boolean readError; boolean readError;
public final EventHandler<SimpleEvent<String>> printlnEvent = new EventHandler<>(); public final EventHandler<SimpleEvent<String>> printlnEvent = new EventHandler<>();
@ -48,6 +52,13 @@ public class ProcessThread extends Thread {
return monitor.getProcess(); return monitor.getProcess();
} }
/**
* Only get stdout or stderr output according to readError().
*/
public List<String> getLines() {
return lines;
}
@Override @Override
public void run() { public void run() {
setName("ProcessMonitor"); setName("ProcessMonitor");
@ -62,18 +73,22 @@ public class ProcessThread extends Thread {
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
printlnEvent.fire(new SimpleEvent<>(monitor, line)); printlnEvent.fire(new SimpleEvent<>(monitor, line));
System.out.println("MC: " + line); System.out.println("MC: " + line);
lines.add(line);
p.getStdOutLines().add(line); p.getStdOutLines().add(line);
} }
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
printlnEvent.fire(new SimpleEvent<>(monitor, line)); printlnEvent.fire(new SimpleEvent<>(monitor, line));
System.out.println("MC: " + line); System.out.println("MC: " + line);
lines.add(line);
p.getStdOutLines().add(line); p.getStdOutLines().add(line);
} }
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);
} finally { } finally {
IOUtils.closeQuietly(br); IOUtils.closeQuietly(br);
} }
if (p instanceof JavaProcess)
((JavaProcess) p).getLatch().countDown();
stopEvent.fire(new SimpleEvent<>(this, p));
} }
} }