mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
Merge pull request #866 from mitchellh/termio-deadlock
termio: Fix deadlock when writer mailbox is full
This commit is contained in:
@ -1398,16 +1398,29 @@ const StreamHandler = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fn messageWriter(self: *StreamHandler, msg: termio.Message) void {
|
inline fn messageWriter(self: *StreamHandler, msg: termio.Message) void {
|
||||||
// Try to write to the mailbox with an instant timeout. If the
|
// Try to write to the mailbox with an instant timeout. This is the
|
||||||
// mailbox is full, then we wake up the writer thread mid-processing
|
// fast path because we can queue without a lock.
|
||||||
// so it can process the message and then try again with a forever
|
|
||||||
// wait.
|
|
||||||
if (self.ev.writer_mailbox.push(msg, .{ .instant = {} }) == 0) {
|
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| {
|
self.ev.writer_wakeup.notify() catch |err| {
|
||||||
log.warn("failed to wake up writer, data will be dropped err={}", .{err});
|
log.warn("failed to wake up writer, data will be dropped err={}", .{err});
|
||||||
return;
|
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 = {} });
|
_ = self.ev.writer_mailbox.push(msg, .{ .forever = {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user