core: fix encoded key request cleanup

Encoded key requests are owned by the caller until they are added to a
key sequence or queued for IO. The child_exited path and failed queue
append returned without freeing the allocated request.

The existing errdefer was also too broad: after queueIo took ownership, a
later setSelection or queueRender error could free the queued request.

We now free requests in the return paths that still own them, and the
errdefer has been removed.

Also, activate a sequence only after encoding and queue append succeed
so failure preserves the previous sequence state.
This commit is contained in:
Jon Parise
2026-08-05 13:35:30 -04:00
parent 46767b5213
commit 0060d89b5b

View File

@@ -858,7 +858,7 @@ inline fn surfaceMailbox(self: *Surface) Mailbox {
};
}
/// Queue a message for the IO thread.
/// Queue a message for the IO thread, taking ownership of `msg`.
///
/// We centralize all our logic into this spot so we can intercept
/// messages for example in readonly mode.
@@ -2824,11 +2824,11 @@ pub fn keyCallback(
// an encoded value, we close the surface. We want to eventually
// move this behavior to the apprt probably.
if (self.child_exited) {
write_req.deinit();
self.close();
return .closed;
}
errdefer write_req.deinit();
self.queueIo(switch (write_req) {
.small => |v| .{ .write_small = v },
.stable => |v| .{ .write_stable = v },
@@ -2946,16 +2946,19 @@ fn maybeHandleBinding(
// Determine if this entry has an action or if its a leader key.
const leaf: input.Binding.Set.GenericLeaf = switch (entry.value_ptr.*) {
.leader => |set| {
// Setup the next set we'll look at.
self.keyboard.sequence_set = set;
// Store this event so that we can drain and encode on invalid.
// We don't need to cap this because it is naturally capped by
// the config validation.
if (try self.encodeKey(event, insp_ev)) |req| {
try self.keyboard.sequence_queued.append(self.alloc, req);
self.keyboard.sequence_queued.append(self.alloc, req) catch |err| {
req.deinit();
return err;
};
}
// Setup the next set we'll look at only after all fallible work.
self.keyboard.sequence_set = set;
// Start or continue our key sequence
_ = self.rt_app.performAction(
.{ .surface = self },