Skip to content

Commit

Permalink
Merge pull request #866 from mitchellh/termio-deadlock
Browse files Browse the repository at this point in the history
termio: Fix deadlock when writer mailbox is full
  • Loading branch information
mitchellh authored Nov 12, 2023
2 parents b3dd07a + c8ffc90 commit cfdd996
Showing 1 changed file with 17 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/termio/Exec.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1398,16 +1398,29 @@ const StreamHandler = struct {
}

inline fn messageWriter(self: *StreamHandler, msg: termio.Message) void {
// Try to write to the mailbox with an instant timeout. If the
// mailbox is full, then we wake up the writer thread mid-processing
// so it can process the message and then try again with a forever
// wait.
// Try to write to the mailbox with an instant timeout. This is the
// fast path because we can queue without a lock.
if (self.ev.writer_mailbox.push(msg, .{ .instant = {} }) == 0) {
// If we enter this conditional, the mailbox is full. We wake up
// the writer thread so that it can process messages to clear up
// space. However, the writer thread may require the renderer
// lock so we need to unlock.
self.ev.writer_wakeup.notify() catch |err| {
log.warn("failed to wake up writer, data will be dropped err={}", .{err});
return;
};

// Unlock the renderer state so the writer thread can acquire it.
// Then try to queue our message before continuing. This is a very
// slow path because we are having a lot of contention for data.
// But this only gets triggered in certain pathological cases.
//
// Note that writes themselves don't require a lock, but there
// are other messages in the writer mailbox (resize, focus) that
// could acquire the lock. This is why we have to release our lock
// here.
self.ev.renderer_state.mutex.unlock();
defer self.ev.renderer_state.mutex.lock();
_ = self.ev.writer_mailbox.push(msg, .{ .forever = {} });
}

Expand Down

0 comments on commit cfdd996

Please sign in to comment.