9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-19 15:09:25 +00:00

fix server stuck on wait shutdown

This commit is contained in:
hayanesuru
2025-06-10 21:06:30 +09:00
parent e00bf47f33
commit b6ec152037
4 changed files with 32 additions and 11 deletions

View File

@@ -28,10 +28,10 @@ public class AsyncExecutor implements Runnable {
thread.start(); thread.start();
} }
public void kill() throws InterruptedException { public void join(long millis) throws InterruptedException {
killswitch = true; killswitch = true;
LockSupport.unpark(thread); LockSupport.unpark(thread);
thread.join(); thread.join(millis);
} }
public void submit(Runnable runnable) { public void submit(Runnable runnable) {

View File

@@ -1,37 +1,58 @@
package org.dreeam.leaf.async; package org.dreeam.leaf.async;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dreeam.leaf.async.ai.AsyncGoalThread;
import org.dreeam.leaf.async.path.AsyncPathProcessor;
import org.dreeam.leaf.async.tracker.MultithreadedTracker; import org.dreeam.leaf.async.tracker.MultithreadedTracker;
public class ShutdownExecutors { import java.util.concurrent.TimeUnit;
public static void shutdown(MinecraftServer server) {
public class ShutdownExecutors {
public static final Logger LOGGER = LogManager.getLogger("Leaf");
public static void shutdown(MinecraftServer server) {
if (server.mobSpawnExecutor != null) { if (server.mobSpawnExecutor != null) {
LOGGER.info("Waiting for mob spawning thread to shutdown...");
try { try {
server.mobSpawnExecutor.kill(); server.mobSpawnExecutor.join(3000L);
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
} }
} }
if (AsyncPlayerDataSaving.IO_POOL != null) { if (AsyncPlayerDataSaving.IO_POOL != null) {
LOGGER.info("Waiting for player I/O executor to shutdown...");
AsyncPlayerDataSaving.IO_POOL.shutdown(); AsyncPlayerDataSaving.IO_POOL.shutdown();
try { try {
AsyncPlayerDataSaving.IO_POOL.awaitTermination(300L, java.util.concurrent.TimeUnit.SECONDS); AsyncPlayerDataSaving.IO_POOL.awaitTermination(60L, TimeUnit.SECONDS);
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
} }
} }
if (server.asyncGoalThread != null) { if (server.asyncGoalThread != null) {
LOGGER.info("Waiting for mob target finding thread to shutdown...");
AsyncGoalThread.RUNNING = false;
try { try {
server.asyncGoalThread.join(); server.asyncGoalThread.join(3000L);
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
} }
} }
if (MultithreadedTracker.TRACKER_EXECUTOR != null) { if (MultithreadedTracker.TRACKER_EXECUTOR != null) {
LOGGER.info("Waiting for mob tracker executor to shutdown...");
MultithreadedTracker.TRACKER_EXECUTOR.shutdown(); MultithreadedTracker.TRACKER_EXECUTOR.shutdown();
try { try {
MultithreadedTracker.TRACKER_EXECUTOR.awaitTermination(10L, java.util.concurrent.TimeUnit.SECONDS); MultithreadedTracker.TRACKER_EXECUTOR.awaitTermination(10L, TimeUnit.SECONDS);
} catch (InterruptedException ignored) {
}
}
if (AsyncPathProcessor.pathProcessingExecutor != null) {
LOGGER.info("Waiting for mob pathfinding executor to shutdown...");
AsyncPathProcessor.pathProcessingExecutor.shutdown();
try {
AsyncPathProcessor.pathProcessingExecutor.awaitTermination(10L, TimeUnit.SECONDS);
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
} }
} }

View File

@@ -8,7 +8,7 @@ import java.util.OptionalInt;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
public class AsyncGoalThread extends Thread { public class AsyncGoalThread extends Thread {
public static volatile boolean RUNNING = true;
public AsyncGoalThread(final MinecraftServer server) { public AsyncGoalThread(final MinecraftServer server) {
super(() -> run(server), "Leaf Async Goal Thread"); super(() -> run(server), "Leaf Async Goal Thread");
this.setDaemon(false); this.setDaemon(false);
@@ -18,7 +18,7 @@ public class AsyncGoalThread extends Thread {
} }
private static void run(MinecraftServer server) { private static void run(MinecraftServer server) {
while (server.isRunning()) { while (RUNNING) {
boolean retry = false; boolean retry = false;
for (ServerLevel level : server.getAllLevels()) { for (ServerLevel level : server.getAllLevels()) {
var exec = level.asyncGoalExecutor; var exec = level.asyncGoalExecutor;

View File

@@ -28,7 +28,7 @@ public class AsyncPathProcessor {
private static final String THREAD_PREFIX = "Leaf Async Pathfinding"; private static final String THREAD_PREFIX = "Leaf Async Pathfinding";
private static final Logger LOGGER = LogManager.getLogger(THREAD_PREFIX); private static final Logger LOGGER = LogManager.getLogger(THREAD_PREFIX);
private static long lastWarnMillis = System.currentTimeMillis(); private static long lastWarnMillis = System.currentTimeMillis();
private static final ThreadPoolExecutor pathProcessingExecutor = new ThreadPoolExecutor( public static final ThreadPoolExecutor pathProcessingExecutor = new ThreadPoolExecutor(
1, 1,
AsyncPathfinding.asyncPathfindingMaxThreads, AsyncPathfinding.asyncPathfindingMaxThreads,
AsyncPathfinding.asyncPathfindingKeepalive, TimeUnit.SECONDS, AsyncPathfinding.asyncPathfindingKeepalive, TimeUnit.SECONDS,