mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-08-04 03:46:57 -04:00
Merge 449a6f1386002a38c34422098002e950928f706a into 9969dc60c5278340b6b9a4d7facdde620e99d1f5
This commit is contained in:
commit
33b54b39bb
@ -25,6 +25,7 @@ import org.jackhuang.hmcl.util.Log4jLevel;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
import org.jackhuang.hmcl.util.platform.ManagedProcess;
|
||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||
import org.jackhuang.hmcl.util.platform.SystemUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -54,7 +55,7 @@ final class ExitWaiter implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int exitCode = process.getProcess().waitFor();
|
||||
int exitCode = SystemUtils.waitFor(process.getProcess());
|
||||
|
||||
for (Thread thread : joins)
|
||||
thread.join();
|
||||
|
@ -205,7 +205,7 @@ public enum Architecture {
|
||||
if (CURRENT_ARCH == X86_64) {
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(new String[]{"/usr/sbin/sysctl", "-n", "sysctl.proc_translated"});
|
||||
if (process.waitFor(3, TimeUnit.SECONDS) && process.exitValue() == 0
|
||||
if (SystemUtils.waitFor(process, 3, TimeUnit.SECONDS) && process.exitValue() == 0
|
||||
&& "1".equals(IOUtils.readFullyAsString(process.getInputStream(), OperatingSystem.NATIVE_CHARSET).trim())) {
|
||||
sysArch = ARM64;
|
||||
}
|
||||
@ -221,7 +221,7 @@ public enum Architecture {
|
||||
if (new File(uname).exists()) {
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(new String[]{uname, "-m"});
|
||||
if (process.waitFor(3, TimeUnit.SECONDS) && process.exitValue() == 0) {
|
||||
if (SystemUtils.waitFor(process, 3, TimeUnit.SECONDS) && process.exitValue() == 0) {
|
||||
sysArch = parseArchName(IOUtils.readFullyAsString(process.getInputStream(), OperatingSystem.NATIVE_CHARSET).trim());
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
|
@ -72,7 +72,7 @@ public final class SystemUtils {
|
||||
ManagedProcess managedProcess = new ManagedProcess(processBuilder);
|
||||
managedProcess.pumpInputStream(SystemUtils::onLogLine);
|
||||
managedProcess.pumpErrorStream(SystemUtils::onLogLine);
|
||||
return managedProcess.getProcess().waitFor();
|
||||
return waitFor(managedProcess.getProcess());
|
||||
}
|
||||
|
||||
public static String run(String... command) throws Exception {
|
||||
@ -95,7 +95,7 @@ public final class SystemUtils {
|
||||
Lang.wrap(() -> convert.apply(inputStream)),
|
||||
Schedulers.io());
|
||||
|
||||
if (!process.waitFor(15, TimeUnit.SECONDS))
|
||||
if (!SystemUtils.waitFor(process, 15, TimeUnit.SECONDS))
|
||||
throw new TimeoutException();
|
||||
|
||||
if (process.exitValue() != 0)
|
||||
@ -115,4 +115,58 @@ public final class SystemUtils {
|
||||
private static void onLogLine(String log) {
|
||||
LOG.info(log);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>A low performance implementation of {@link Process#waitFor()}</p>
|
||||
*
|
||||
* <p>
|
||||
* On Windows, JVM invoke
|
||||
* <a href="https://github.com/openjdk/jdk/blob/b77bd5fd6a6f7ddbed90300fba790da4fb683275/src/java.base/windows/native/libjava/ProcessImpl_md.c#L428-L459">WaitForMultipleObjects</a>
|
||||
* to wait the specific process and VM thread interrupt flag at the same time.
|
||||
* However, this API might throw unexpected exception, causing a IOException on Java level.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The following codes replace native implementation with software ones.
|
||||
* </p>
|
||||
*/
|
||||
public static int waitFor(Process process) throws InterruptedException {
|
||||
if (OperatingSystem.CURRENT_OS != OperatingSystem.WINDOWS) {
|
||||
return process.waitFor();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
return process.exitValue();
|
||||
} catch (IllegalThreadStateException e2) {
|
||||
// noinspection BusyWait
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #waitFor(Process)}
|
||||
*/
|
||||
public static boolean waitFor(Process process, long timeout, TimeUnit unit) throws InterruptedException {
|
||||
if (OperatingSystem.CURRENT_OS != OperatingSystem.WINDOWS) {
|
||||
return process.waitFor(timeout, unit);
|
||||
}
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
long rem = unit.toNanos(timeout);
|
||||
|
||||
do {
|
||||
try {
|
||||
process.exitValue();
|
||||
return true;
|
||||
} catch (IllegalThreadStateException ex) {
|
||||
if (rem > 0)
|
||||
Thread.sleep(
|
||||
Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
|
||||
}
|
||||
rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
|
||||
} while (rem > 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user