Fix potential issue with BackgroundScanHandler for users with slow disc IO (#8176)

This commit is contained in:
DaemonUmbra authored and GitHub committed 2021-11-23 17:05:45 -08:00
1 parent ec7cb00f86
commit a4e574fa6b
1 file changed
+24 -7
@@ -24,6 +24,8 @@ import net.minecraftforge.fml.loading.LoadingModList;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
@@ -32,12 +34,22 @@ import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
public class BackgroundScanHandler
{
private enum ScanStatus {
NOT_STARTED,
RUNNING,
COMPLETE,
TIMED_OUT,
INTERRUPTED,
ERRORED
}
private static final Logger LOGGER = LogManager.getLogger();
private final ExecutorService modContentScanner;
private final List<ModFile> pendingFiles;
private final List<ModFile> scannedFiles;
private final List<ModFile> allFiles;
private final List<ModFile> modFiles;
private ScanStatus status;
private LoadingModList loadingModList;
@SuppressWarnings("UnstableApiUsage")
@@ -51,6 +63,7 @@ public class BackgroundScanHandler
scannedFiles = new ArrayList<>();
pendingFiles = new ArrayList<>();
allFiles = new ArrayList<>();
status = ScanStatus.NOT_STARTED;
}
public List<ModFile> getModFiles() {
@@ -59,8 +72,10 @@ public class BackgroundScanHandler
public void submitForScanning(final ModFile file) {
if (modContentScanner.isShutdown()) {
status = ScanStatus.ERRORED;
throw new IllegalStateException("Scanner has shutdown");
}
status = ScanStatus.RUNNING;
allFiles.add(file);
pendingFiles.add(file);
final CompletableFuture<ModFileScanData> future = CompletableFuture.supplyAsync(file::compileContent, modContentScanner)
@@ -71,6 +86,7 @@ public class BackgroundScanHandler
private void addCompletedFile(final ModFile file, final ModFileScanData modFileScanData, final Throwable throwable) {
if (throwable != null) {
status = ScanStatus.ERRORED;
LOGGER.error(SCAN,"An error occurred scanning file {}", file, throwable);
}
pendingFiles.remove(file);
@@ -88,18 +104,19 @@ public class BackgroundScanHandler
}
public void waitForScanToComplete(final Runnable ticker) {
boolean interrupted = false;
boolean succeeded = false;
boolean timeoutActive = System.getProperty("fml.disableScanTimeout") == null;
Instant deadline = Instant.now().plus(Duration.ofMinutes(10));
modContentScanner.shutdown();
do {
ticker.run();
try {
succeeded = modContentScanner.awaitTermination(50, TimeUnit.MILLISECONDS);
status = modContentScanner.awaitTermination(50, TimeUnit.MILLISECONDS) ? ScanStatus.COMPLETE : ScanStatus.RUNNING;
} catch (InterruptedException e) {
interrupted = true;
status = ScanStatus.INTERRUPTED;
}
} while (!modContentScanner.isShutdown());
if (interrupted) Thread.currentThread().interrupt();
if (!succeeded) throw new IllegalStateException("Failed to complete mod scan");
if (timeoutActive && Instant.now().isAfter(deadline)) status = ScanStatus.TIMED_OUT;
} while (status == ScanStatus.RUNNING);
if (status == ScanStatus.INTERRUPTED) Thread.currentThread().interrupt();
if (status != ScanStatus.COMPLETE) throw new IllegalStateException("Failed to complete mod scan");
}
}