fix memory leak
This commit is contained in:
@@ -11,8 +11,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
public final class Terminal implements AutoCloseable {
|
||||
private final GhosttyLibrary library;
|
||||
private final MemorySegment handle;
|
||||
private final Arena callbackArena = Arena.ofShared();
|
||||
private final AtomicBoolean closed = new AtomicBoolean();
|
||||
private Arena ptyWriterArena;
|
||||
private Arena deviceAttributesArena;
|
||||
private MemorySegment ptyWriterStub = MemorySegment.NULL;
|
||||
private MemorySegment deviceAttributesStub = MemorySegment.NULL;
|
||||
private PtyWriter ptyWriter;
|
||||
@@ -40,26 +41,41 @@ public final class Terminal implements AutoCloseable {
|
||||
public void setPtyWriter(PtyWriter writer) {
|
||||
ensureOpen();
|
||||
ptyWriter = writer;
|
||||
|
||||
// Each upcall stub lives in its own arena so that reassigning (or clearing) the
|
||||
// writer can free the previous stub. The native pointer is repointed before the old
|
||||
// arena is closed, so native never holds a dangling stub.
|
||||
Arena previous = ptyWriterArena;
|
||||
if (writer == null) {
|
||||
ptyWriterStub = MemorySegment.NULL;
|
||||
ptyWriterArena = null;
|
||||
library.terminalSetPointer(handle, GhosttyLibrary.TERMINAL_OPT_WRITE_PTY, MemorySegment.NULL);
|
||||
return;
|
||||
} else {
|
||||
Arena arena = Arena.ofShared();
|
||||
ptyWriterStub = library.upcallPtyWriter(writer, arena);
|
||||
ptyWriterArena = arena;
|
||||
library.terminalSetPointer(handle, GhosttyLibrary.TERMINAL_OPT_WRITE_PTY, ptyWriterStub);
|
||||
}
|
||||
|
||||
ptyWriterStub = library.upcallPtyWriter(writer, callbackArena);
|
||||
library.terminalSetPointer(handle, GhosttyLibrary.TERMINAL_OPT_WRITE_PTY, ptyWriterStub);
|
||||
if (previous != null) {
|
||||
previous.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void setDeviceAttributesProvider(DeviceAttributesProvider provider) {
|
||||
ensureOpen();
|
||||
deviceAttributesProvider = provider;
|
||||
|
||||
// See setPtyWriter: a per-stub arena lets reassignment free the previous stub.
|
||||
Arena previous = deviceAttributesArena;
|
||||
if (provider == null) {
|
||||
deviceAttributesStub = MemorySegment.NULL;
|
||||
deviceAttributesArena = null;
|
||||
library.terminalSetPointer(handle, GhosttyLibrary.TERMINAL_OPT_DEVICE_ATTRIBUTES, MemorySegment.NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
deviceAttributesStub = library.upcallDeviceAttributesProvider(provider, callbackArena);
|
||||
} else {
|
||||
Arena arena = Arena.ofShared();
|
||||
deviceAttributesStub = library.upcallDeviceAttributesProvider(provider, arena);
|
||||
deviceAttributesArena = arena;
|
||||
library.terminalSetPointer(
|
||||
handle,
|
||||
GhosttyLibrary.TERMINAL_OPT_DEVICE_ATTRIBUTES,
|
||||
@@ -67,6 +83,11 @@ public final class Terminal implements AutoCloseable {
|
||||
);
|
||||
}
|
||||
|
||||
if (previous != null) {
|
||||
previous.close();
|
||||
}
|
||||
}
|
||||
|
||||
public String text() {
|
||||
return format(TerminalFormat.PLAIN);
|
||||
}
|
||||
@@ -156,7 +177,14 @@ public final class Terminal implements AutoCloseable {
|
||||
public void close() {
|
||||
if (closed.compareAndSet(false, true)) {
|
||||
library.terminalFree(handle);
|
||||
callbackArena.close();
|
||||
if (ptyWriterArena != null) {
|
||||
ptyWriterArena.close();
|
||||
ptyWriterArena = null;
|
||||
}
|
||||
if (deviceAttributesArena != null) {
|
||||
deviceAttributesArena.close();
|
||||
deviceAttributesArena = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user