fix memory leak
This commit is contained in:
@@ -11,8 +11,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
public final class Terminal implements AutoCloseable {
|
public final class Terminal implements AutoCloseable {
|
||||||
private final GhosttyLibrary library;
|
private final GhosttyLibrary library;
|
||||||
private final MemorySegment handle;
|
private final MemorySegment handle;
|
||||||
private final Arena callbackArena = Arena.ofShared();
|
|
||||||
private final AtomicBoolean closed = new AtomicBoolean();
|
private final AtomicBoolean closed = new AtomicBoolean();
|
||||||
|
private Arena ptyWriterArena;
|
||||||
|
private Arena deviceAttributesArena;
|
||||||
private MemorySegment ptyWriterStub = MemorySegment.NULL;
|
private MemorySegment ptyWriterStub = MemorySegment.NULL;
|
||||||
private MemorySegment deviceAttributesStub = MemorySegment.NULL;
|
private MemorySegment deviceAttributesStub = MemorySegment.NULL;
|
||||||
private PtyWriter ptyWriter;
|
private PtyWriter ptyWriter;
|
||||||
@@ -40,26 +41,41 @@ public final class Terminal implements AutoCloseable {
|
|||||||
public void setPtyWriter(PtyWriter writer) {
|
public void setPtyWriter(PtyWriter writer) {
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
ptyWriter = writer;
|
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) {
|
if (writer == null) {
|
||||||
ptyWriterStub = MemorySegment.NULL;
|
ptyWriterStub = MemorySegment.NULL;
|
||||||
|
ptyWriterArena = null;
|
||||||
library.terminalSetPointer(handle, GhosttyLibrary.TERMINAL_OPT_WRITE_PTY, MemorySegment.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);
|
if (previous != null) {
|
||||||
library.terminalSetPointer(handle, GhosttyLibrary.TERMINAL_OPT_WRITE_PTY, ptyWriterStub);
|
previous.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeviceAttributesProvider(DeviceAttributesProvider provider) {
|
public void setDeviceAttributesProvider(DeviceAttributesProvider provider) {
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
deviceAttributesProvider = provider;
|
deviceAttributesProvider = provider;
|
||||||
|
|
||||||
|
// See setPtyWriter: a per-stub arena lets reassignment free the previous stub.
|
||||||
|
Arena previous = deviceAttributesArena;
|
||||||
if (provider == null) {
|
if (provider == null) {
|
||||||
deviceAttributesStub = MemorySegment.NULL;
|
deviceAttributesStub = MemorySegment.NULL;
|
||||||
|
deviceAttributesArena = null;
|
||||||
library.terminalSetPointer(handle, GhosttyLibrary.TERMINAL_OPT_DEVICE_ATTRIBUTES, MemorySegment.NULL);
|
library.terminalSetPointer(handle, GhosttyLibrary.TERMINAL_OPT_DEVICE_ATTRIBUTES, MemorySegment.NULL);
|
||||||
return;
|
} else {
|
||||||
}
|
Arena arena = Arena.ofShared();
|
||||||
|
deviceAttributesStub = library.upcallDeviceAttributesProvider(provider, arena);
|
||||||
deviceAttributesStub = library.upcallDeviceAttributesProvider(provider, callbackArena);
|
deviceAttributesArena = arena;
|
||||||
library.terminalSetPointer(
|
library.terminalSetPointer(
|
||||||
handle,
|
handle,
|
||||||
GhosttyLibrary.TERMINAL_OPT_DEVICE_ATTRIBUTES,
|
GhosttyLibrary.TERMINAL_OPT_DEVICE_ATTRIBUTES,
|
||||||
@@ -67,6 +83,11 @@ public final class Terminal implements AutoCloseable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (previous != null) {
|
||||||
|
previous.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String text() {
|
public String text() {
|
||||||
return format(TerminalFormat.PLAIN);
|
return format(TerminalFormat.PLAIN);
|
||||||
}
|
}
|
||||||
@@ -156,7 +177,14 @@ public final class Terminal implements AutoCloseable {
|
|||||||
public void close() {
|
public void close() {
|
||||||
if (closed.compareAndSet(false, true)) {
|
if (closed.compareAndSet(false, true)) {
|
||||||
library.terminalFree(handle);
|
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