Fix bug where Buffers were never freed
The issue was that, when reiniting Buffers, the intrusive linkedlist node was clobbered and we lost reference to it. That meant most of the Buffers would be memory leaks. Now, we save the node during reinitializion.
This commit is contained in:
parent
678d0563ed
commit
411f679491
3 changed files with 14 additions and 5 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
These are in rough order of my priority, though no promises I do them in this order.
|
These are in rough order of my priority, though no promises I do them in this order.
|
||||||
|
|
||||||
|
- [ ] Fix mouse resizing
|
||||||
- [ ] Add gap support
|
- [ ] Add gap support
|
||||||
- [ ] Support window tag/order caching between WM restarts (within a river session)
|
- [ ] Support window tag/order caching between WM restarts (within a river session)
|
||||||
- [ ] Add build-time options for including the wallpaper (and maybe bar)
|
- [ ] Add build-time options for including the wallpaper (and maybe bar)
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,15 @@ pub fn init(shm: *wl.Shm, width: u31, height: u31) !Buffer {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Re-initialize this buffer with new dimensions, preserving its position in
|
||||||
|
/// any intrusive linked list. Equivalent to deinit + init but keeps node intact.
|
||||||
|
pub fn reinit(buffer: *Buffer, shm: *wl.Shm, width: u31, height: u31) !void {
|
||||||
|
const saved_node = buffer.node;
|
||||||
|
buffer.deinit();
|
||||||
|
buffer.* = try Buffer.init(shm, width, height);
|
||||||
|
buffer.node = saved_node;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(buffer: *Buffer) void {
|
pub fn deinit(buffer: *Buffer) void {
|
||||||
_ = buffer.pixman_image.unref();
|
_ = buffer.pixman_image.unref();
|
||||||
buffer.wl_buffer.destroy();
|
buffer.wl_buffer.destroy();
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ pub fn deinit(buffer_pool: *BufferPool) void {
|
||||||
/// Get a buffer with the specified dimensions. If possible, an idle buffer is
|
/// Get a buffer with the specified dimensions. If possible, an idle buffer is
|
||||||
/// reused, otherwise a new one is created.
|
/// reused, otherwise a new one is created.
|
||||||
pub fn nextBuffer(buffer_pool: *BufferPool, wl_shm: *wl.Shm, width: u31, height: u31) !*Buffer {
|
pub fn nextBuffer(buffer_pool: *BufferPool, wl_shm: *wl.Shm, width: u31, height: u31) !*Buffer {
|
||||||
log.debug("looking for buffer with dimensions {}x{}, total existing buffers: {}", .{ width, height, buffer_pool.len });
|
log.debug("Looking for buffer with dimensions {}x{}, total existing buffers: {}", .{ width, height, buffer_pool.len });
|
||||||
defer {
|
defer {
|
||||||
// Clear up extra buffers
|
// Clear up extra buffers
|
||||||
if (buffer_pool.len > max_buffer_multiplicity * buffer_pool.surface_count) {
|
if (buffer_pool.len > max_buffer_multiplicity * buffer_pool.surface_count) {
|
||||||
|
|
@ -71,8 +71,7 @@ fn findSuitableBuffer(buffer_pool: *BufferPool, wl_shm: *wl.Shm, width: u31, hei
|
||||||
// No buffer has matching dimensions, however we do have an unbusy
|
// No buffer has matching dimensions, however we do have an unbusy
|
||||||
// buffer which we can just re-init.
|
// buffer which we can just re-init.
|
||||||
if (first_unbusy_buffer) |buffer| {
|
if (first_unbusy_buffer) |buffer| {
|
||||||
buffer.deinit();
|
try buffer.reinit(wl_shm, width, height);
|
||||||
buffer.* = try Buffer.init(wl_shm, width, height);
|
|
||||||
buffer.setListener();
|
buffer.setListener();
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +80,7 @@ fn findSuitableBuffer(buffer_pool: *BufferPool, wl_shm: *wl.Shm, width: u31, hei
|
||||||
}
|
}
|
||||||
|
|
||||||
fn newBuffer(buffer_pool: *BufferPool, wl_shm: *wl.Shm, width: u31, height: u31) !*Buffer {
|
fn newBuffer(buffer_pool: *BufferPool, wl_shm: *wl.Shm, width: u31, height: u31) !*Buffer {
|
||||||
log.debug("creating new buffer {}x{}", .{ width, height });
|
log.debug("Creating new {}x{} buffer", .{ width, height });
|
||||||
const buffer = try utils.gpa.create(Buffer);
|
const buffer = try utils.gpa.create(Buffer);
|
||||||
errdefer utils.gpa.destroy(buffer);
|
errdefer utils.gpa.destroy(buffer);
|
||||||
buffer.* = try Buffer.init(wl_shm, width, height);
|
buffer.* = try Buffer.init(wl_shm, width, height);
|
||||||
|
|
@ -92,8 +91,8 @@ fn newBuffer(buffer_pool: *BufferPool, wl_shm: *wl.Shm, width: u31, height: u31)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cullBuffers(buffer_pool: *BufferPool) void {
|
fn cullBuffers(buffer_pool: *BufferPool) void {
|
||||||
log.debug("culling extra buffers", .{});
|
|
||||||
var overhead = buffer_pool.len - max_buffer_multiplicity * buffer_pool.surface_count;
|
var overhead = buffer_pool.len - max_buffer_multiplicity * buffer_pool.surface_count;
|
||||||
|
log.debug("Culling extra buffers {d}->{d}", .{ buffer_pool.len, buffer_pool.surface_count });
|
||||||
var it = buffer_pool.buffers.first;
|
var it = buffer_pool.buffers.first;
|
||||||
while (it) |node| {
|
while (it) |node| {
|
||||||
if (overhead == 0) break;
|
if (overhead == 0) break;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue