Skip to content

Commit e36ba04

Browse files
Moulberryembeddedt
authored andcommitted
Avoid mods causing double free when BufferBuilder leak fix is enabled
1 parent 4054bd8 commit e36ba04

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/buffer_builder_leak/BufferBuilderMixin.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import com.mojang.blaze3d.vertex.BufferBuilder;
44
import org.embeddedt.modernfix.ModernFix;
5-
import org.lwjgl.system.MemoryUtil;
5+
import org.embeddedt.modernfix.render.UnsafeBufferHelper;
66
import org.spongepowered.asm.mixin.Mixin;
77
import org.spongepowered.asm.mixin.Shadow;
88

@@ -12,7 +12,6 @@
1212
public class BufferBuilderMixin {
1313
@Shadow private ByteBuffer buffer;
1414

15-
private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false);
1615
private static boolean leakReported = false;
1716

1817
@Override
@@ -25,7 +24,7 @@ protected void finalize() throws Throwable {
2524
leakReported = true;
2625
ModernFix.LOGGER.warn("One or more BufferBuilders have been leaked, ModernFix will attempt to correct this.");
2726
}
28-
ALLOCATOR.free(MemoryUtil.memAddress0(buf));
27+
UnsafeBufferHelper.free(buf);
2928
buffer = null;
3029
}
3130
} finally {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.embeddedt.modernfix.render;
2+
3+
import org.embeddedt.modernfix.ModernFix;
4+
import org.lwjgl.system.MemoryUtil;
5+
import sun.misc.Unsafe;
6+
7+
import java.lang.reflect.Field;
8+
import java.nio.ByteBuffer;
9+
10+
/**
11+
* Helper that frees ByteBuffers allocated by BufferBuilders, and nulls out the address pointer
12+
* to prevent double frees.
13+
*
14+
* @author Moulberry
15+
*/
16+
public class UnsafeBufferHelper {
17+
private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false);
18+
19+
private static sun.misc.Unsafe UNSAFE = null;
20+
private static long ADDRESS = -1;
21+
22+
static {
23+
try {
24+
final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
25+
theUnsafe.setAccessible(true);
26+
UNSAFE = (Unsafe)theUnsafe.get(null);
27+
28+
final Field addressField = MemoryUtil.class.getDeclaredField("ADDRESS");
29+
addressField.setAccessible(true);
30+
ADDRESS = addressField.getLong(null);
31+
} catch(Throwable t) {
32+
ModernFix.LOGGER.error("Could load unsafe/buffer address", t);
33+
}
34+
}
35+
36+
public static void free(ByteBuffer buf) {
37+
if(UNSAFE != null && ADDRESS >= 0) {
38+
// set the address to 0 to prevent double free
39+
long address = UNSAFE.getAndSetLong(buf, ADDRESS, 0);
40+
if(address != 0) {
41+
ALLOCATOR.free(address);
42+
}
43+
} else {
44+
ALLOCATOR.free(MemoryUtil.memAddress0(buf));
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)