Fix f3 msg causing mem leaks & render file throwing (harmless) exceptions on shutdown

This commit is contained in:
TomTheFurry
2023-07-16 17:23:31 +08:00
parent 060dca1574
commit 51bb3eec3d
9 changed files with 55 additions and 40 deletions
@@ -205,16 +205,10 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
})
.whenComplete((fullDataSource, ex) ->
{
if (ex instanceof CompletionException) {
ex = ex.getCause();
}
if (ex instanceof InterruptedException || ex instanceof RejectedExecutionException)
{
// this exception can be ignored
}
else if (ex != null) {
if (ex != null && !LodUtil.isInterruptOrReject(ex)) {
LOGGER.error("Error updating file "+this.file+": ", ex);
}
if (fullDataSource != null) {
new DataObjTracker(fullDataSource);
new DataObjSoftTracker(this, fullDataSource);
@@ -14,6 +14,7 @@ import com.seibel.distanthorizons.core.level.IDhClientLevel;
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
import com.seibel.distanthorizons.core.util.AtomicsUtil;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataInputStream;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
@@ -222,7 +223,8 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
{
if (ex != null)
{
LOGGER.error("Uncaught error on creation {}: ", this.file, ex);
if (!LodUtil.isInterruptOrReject(ex))
LOGGER.error("Uncaught error on creation {}: ", this.file, ex);
cachedRenderDataSource = new SoftReference<>(null);
renderSourceLoadFutureRef.set(null);
future.complete(null);
@@ -263,7 +265,8 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
{
if (ex != null)
{
LOGGER.error("Error loading file {}: ", this.file, ex);
if (!LodUtil.isInterruptOrReject(ex))
LOGGER.error("Error loading file {}: ", this.file, ex);
cachedRenderDataSource = new SoftReference<>(null);
renderSourceLoadFutureRef.set(null);
future.complete(null);
@@ -418,7 +418,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
int ignoreEmptyWarning = 0;
}
else if (!UncheckedInterruptedException.isThrowableInterruption(ex))
else if (!UncheckedInterruptedException.isInterrupt(ex))
{
LOGGER.error("Exception when updating render file using data source: ", ex);
}
@@ -14,13 +14,9 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.transformers.LodDataBuilder;
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataFileHandler;
import com.seibel.distanthorizons.core.generation.tasks.*;
import com.seibel.distanthorizons.core.pos.*;
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
import com.seibel.distanthorizons.core.util.ThreadUtil;
import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode;
import com.seibel.distanthorizons.core.util.objects.quadTree.QuadTree;
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
@@ -430,7 +426,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
if (exception != null)
{
// don't log the shutdown exceptions
if (!UncheckedInterruptedException.isThrowableInterruption(exception)
if (!UncheckedInterruptedException.isInterrupt(exception)
&& !(exception instanceof CancellationException || exception.getCause() instanceof CancellationException))
{
LOGGER.error("Error generating data for section "+taskPos, exception);
@@ -566,7 +562,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
exception = exception.getCause();
}
if (!UncheckedInterruptedException.isThrowableInterruption(exception) && !(exception instanceof CancellationException))
if (!UncheckedInterruptedException.isInterrupt(exception) && !(exception instanceof CancellationException))
{
LOGGER.error("Error when terminating data generation for section "+runningTaskGroup.group.pos, exception);
}
@@ -23,10 +23,11 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
import org.apache.logging.log4j.Logger;
import java.io.Closeable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
public class ClientLevelModule {
public class ClientLevelModule implements Closeable {
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private final IDhClientLevel parent;
@@ -192,6 +193,7 @@ public class ClientLevelModule {
ClientRenderState.close();
}
}
f3Message.close();
}
@@ -3,10 +3,7 @@ package com.seibel.distanthorizons.core.logging.f3;
import com.seibel.distanthorizons.coreapi.ModInfo;
import java.io.Closeable;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.*;
import java.util.function.Supplier;
public class F3Screen
@@ -15,22 +12,25 @@ public class F3Screen
"", // blank line for spacing
ModInfo.READABLE_NAME + " version: " + ModInfo.VERSION
};
private static final LinkedList<Message> SELF_UPDATE_MESSAGE_LIST = new LinkedList<>();
private static final List<Message> SELF_UPDATE_MESSAGE_LIST = Collections.synchronizedList(new LinkedList<>());
public static void addStringToDisplay(List<String> list)
{
list.addAll(Arrays.asList(DEFAULT_STRING));
Iterator<Message> iterator = SELF_UPDATE_MESSAGE_LIST.iterator();
while (iterator.hasNext())
{
Message message = iterator.next();
if (message == null)
synchronized (SELF_UPDATE_MESSAGE_LIST)
{
Iterator<Message> iterator = SELF_UPDATE_MESSAGE_LIST.iterator();
while (iterator.hasNext())
{
iterator.remove();
}
else
{
message.printTo(list);
Message message = iterator.next();
if (message == null)
{
iterator.remove();
}
else
{
message.printTo(list);
}
}
}
}
@@ -45,12 +45,16 @@ public class F3Screen
// and because this class shouldn't be used in a try {} block.
public static abstract class Message implements Closeable
{
protected Message() { SELF_UPDATE_MESSAGE_LIST.add(this); }
protected Message() {
SELF_UPDATE_MESSAGE_LIST.add(this);
}
public abstract void printTo(List<String> output);
@Override
public void close() { SELF_UPDATE_MESSAGE_LIST.remove(this); }
public void close() {
boolean removed = SELF_UPDATE_MESSAGE_LIST.remove(this);
}
}
public static class StaticMessage extends Message
@@ -20,6 +20,8 @@
package com.seibel.distanthorizons.core.util;
import java.util.Iterator;
import java.util.concurrent.CompletionException;
import java.util.concurrent.RejectedExecutionException;
import com.seibel.distanthorizons.api.enums.config.EVanillaOverdraw;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
@@ -29,6 +31,7 @@ import com.seibel.distanthorizons.core.pos.Pos2D;
import com.seibel.distanthorizons.core.render.vertexFormat.DefaultLodVertexFormats;
import com.seibel.distanthorizons.core.render.vertexFormat.LodVertexFormat;
import com.seibel.distanthorizons.core.util.gridList.EdgeDistanceBooleanGrid;
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper;
@@ -297,6 +300,15 @@ public class LodUtil
public static void assertToDo() {
throw new AssertFailureException("TODO!");
}
public static Throwable ensureUnwrap(Throwable t) {
return t instanceof CompletionException ? ensureUnwrap(t.getCause()) : t;
}
public static boolean isInterruptOrReject(Throwable t) {
Throwable unwrapped = LodUtil.ensureUnwrap(t);
return UncheckedInterruptedException.isInterrupt(unwrapped) ||
unwrapped instanceof RejectedExecutionException;
}
}
@@ -1,5 +1,7 @@
package com.seibel.distanthorizons.core.util.objects;
import com.seibel.distanthorizons.core.util.LodUtil;
import java.util.concurrent.CompletionException;
public class UncheckedInterruptedException extends RuntimeException {
@@ -38,8 +40,8 @@ public class UncheckedInterruptedException extends RuntimeException {
rethrowIfIsInterruption(t.getCause());
}
}
public static boolean isThrowableInterruption(Throwable t) {
return t instanceof InterruptedException || t instanceof UncheckedInterruptedException
|| (t instanceof CompletionException && isThrowableInterruption(t.getCause()));
public static boolean isInterrupt(Throwable t) {
Throwable unwrapped = LodUtil.ensureUnwrap(t);
return unwrapped instanceof InterruptedException || unwrapped instanceof UncheckedInterruptedException;
}
}
@@ -101,7 +101,9 @@ public class DhClientServerWorld extends AbstractDhWorld implements IDhClientWor
}
else
{
// TODO why is this called here?
// If the level wrapper is a Client Level Wrapper, then that means the client side leaves the level,
// but note that the server side still has the level loaded. So, we don't want to unload the level,
// we just want to stop rendering it.
this.levelObjMap.remove(wrapper).stopRenderer(); // Ignore resource warning. The level obj is referenced elsewhere.
}
}