Describe the bug
OC2R hangs the server on shutdown. This is caused by threads not being stopped right, specifically Internet and Block Device Initializer.
To Reproduce
Run OC2R on a multiplayer server and stop the server, it will hang.
On linux you can view the java threads with jcmd $(pgrep -f forge) Thread.print 2>/dev/null, look for the threads not labeled daemon. those threads will be there.
Log files
None relevant, shows clean shutdown.
Expected behavior
OC2R to not hang the server on shutdown
Versions (please complete the following information):
- Minecraft: 1.20.1
- Forge: 47.4.20
- oc2: latest dev build
The following diff fixes it but it's heavily AI assisted so don't really want to PR it RN in case something is wrong in a subtle way that isn't obvious to me at the moment.
Diff
diff --git a/src/main/java/li/cil/oc2/common/bus/device/vm/item/AbstractBlockStorageDevice.java b/src/main/java/li/cil/oc2/common/bus/device/vm/item/AbstractBlockStorageDevice.java
index 2f10a52..7f08523 100644
--- a/src/main/java/li/cil/oc2/common/bus/device/vm/item/AbstractBlockStorageDevice.java
+++ b/src/main/java/li/cil/oc2/common/bus/device/vm/item/AbstractBlockStorageDevice.java
@@ -43,7 +43,7 @@ public abstract class AbstractBlockStorageDevice<TBlock extends BlockDevice, TId
protected static final ExecutorService WORKERS = Executors.newCachedThreadPool(r -> {
final Thread thread = new Thread(r, "Block Device Initializer");
- thread.setDaemon(false);
+ thread.setDaemon(true);
return thread;
});
diff --git a/src/main/java/li/cil/oc2/common/event/ForgeEventHandlers.java b/src/main/java/li/cil/oc2/common/event/ForgeEventHandlers.java
index b5b49f3..cd46888 100644
--- a/src/main/java/li/cil/oc2/common/event/ForgeEventHandlers.java
+++ b/src/main/java/li/cil/oc2/common/event/ForgeEventHandlers.java
@@ -3,9 +3,11 @@ package li.cil.oc2.common.event;
import li.cil.oc2.api.API;
import li.cil.oc2.common.config.AsyncConfig;
import li.cil.oc2.common.util.AsyncUtils;
+import li.cil.oc2.common.inet.InternetManagerImpl;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.event.server.ServerAboutToStartEvent;
import net.minecraftforge.event.server.ServerStoppedEvent;
+import net.minecraftforge.event.server.ServerStoppingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.apache.logging.log4j.LogManager;
@@ -37,6 +39,11 @@ public final class ForgeEventHandlers {
LOGGER.info("Server starting, initializing async components");
}
+ @SubscribeEvent
+ public static void onServerStopping(final ServerStoppingEvent event) {
+ InternetManagerImpl.getInstance().ifPresent(manager -> manager.shutdown());
+ }
+
@SubscribeEvent
public static void handleServerStopped(final ServerStoppedEvent event) {
LOGGER.info("Server stopped, cleaning up async components");
diff --git a/src/main/java/li/cil/oc2/common/inet/InternetManagerImpl.java b/src/main/java/li/cil/oc2/common/inet/InternetManagerImpl.java
index 53d55d1..26106aa 100644
--- a/src/main/java/li/cil/oc2/common/inet/InternetManagerImpl.java
+++ b/src/main/java/li/cil/oc2/common/inet/InternetManagerImpl.java
@@ -19,6 +19,7 @@ import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@@ -58,6 +59,18 @@ public final class InternetManagerImpl implements InternetManager {
}
}
+ public void shutdown() {
+ executor.shutdown();
+ try {
+ if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
+ executor.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ executor.shutdownNow();
+ Thread.currentThread().interrupt();
+ }
+ }
+
public static Optional<InternetManagerImpl> getInstance() {
return Optional.ofNullable(INSTANCE);
}
Describe the bug
OC2R hangs the server on shutdown. This is caused by threads not being stopped right, specifically
InternetandBlock Device Initializer.To Reproduce
Run OC2R on a multiplayer server and stop the server, it will hang.
On linux you can view the java threads with
jcmd $(pgrep -f forge) Thread.print 2>/dev/null, look for the threads not labeled daemon. those threads will be there.Log files
None relevant, shows clean shutdown.
Expected behavior
OC2R to not hang the server on shutdown
Versions (please complete the following information):
The following diff fixes it but it's heavily AI assisted so don't really want to PR it RN in case something is wrong in a subtle way that isn't obvious to me at the moment.
Diff