termio: free resources for discarded messages

Messages can own allocated data or a derived config. Some paths (writer
thread draining, mailbox shutdown with unread messages, and queue push
failures) discarded messages without releasing those resources.

This change adds Message.deinit and uses it whenever a message is
discarded.
This commit is contained in:
Jon Parise
2026-08-03 14:24:58 -04:00
parent ac04fc2761
commit 2f7fbadb0b
4 changed files with 20 additions and 6 deletions

View File

@@ -872,10 +872,9 @@ fn queueIo(
switch (msg) {
.write_small,
.write_stable,
=> return,
.write_alloc => |v| {
v.alloc.free(v.data);
.write_alloc,
=> {
msg.deinit();
return;
},

View File

@@ -298,7 +298,7 @@ fn drainMailbox(
// If we're draining, we just drain the mailbox and return.
if (self.flags.drain) {
while (mailbox.pop(global.io())) |_| {}
while (mailbox.pop(global.io())) |msg| msg.deinit();
return;
}

View File

@@ -47,6 +47,7 @@ pub const Mailbox = union(enum) {
pub fn deinit(self: *Mailbox, alloc: Allocator) void {
switch (self.*) {
.spsc => |*v| {
while (v.queue.pop(global.io())) |msg| msg.deinit();
v.queue.destroy(alloc);
v.wakeup.deinit();
},
@@ -76,6 +77,7 @@ pub const Mailbox = union(enum) {
// lock so we need to unlock.
mb.wakeup.notify() catch |err| {
log.warn("failed to wake up writer, data will be dropped err={}", .{err});
msg.deinit();
return;
};
@@ -90,7 +92,7 @@ pub const Mailbox = union(enum) {
// here.
if (mutex) |m| m.unlock(global.io());
defer if (mutex) |m| m.lockUncancelable(global.io());
_ = mb.queue.push(global.io(), msg, .{ .forever = {} });
if (mb.queue.push(global.io(), msg, .{ .forever = {} }) == 0) msg.deinit();
},
}
}

View File

@@ -102,6 +102,19 @@ pub const Message = union(enum) {
};
}
/// Free resources owned by a message that will not be processed.
/// The message is invalid after this call.
pub fn deinit(self: *const Message) void {
switch (self.*) {
.change_config => |v| {
v.ptr.deinit();
v.alloc.destroy(v.ptr);
},
.write_alloc => |v| v.alloc.free(v.data),
else => {},
}
}
/// The types of size reports that we support.
pub const SizeReport = terminal.size_report.Style;
};