From 9f4cb5c4dd5cd80fedd4d1ae47810d8fdba3ec91 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 23 Apr 2025 22:02:17 +0300 Subject: [PATCH] Kernel: Make pseudo terminals not overwrite old data If pseudo terminal buffer was filled, old implementation would overwrite old data. This is bad if producer is capable of producing more data than consumer can handle. --- .../include/kernel/Terminal/PseudoTerminal.h | 4 ++-- kernel/include/kernel/Terminal/Serial.h | 2 +- kernel/include/kernel/Terminal/TTY.h | 4 ++-- kernel/include/kernel/Terminal/VirtualTTY.h | 2 +- kernel/kernel/Terminal/PseudoTerminal.cpp | 20 +++++++++++-------- kernel/kernel/Terminal/Serial.cpp | 3 ++- kernel/kernel/Terminal/TTY.cpp | 13 +++++++----- kernel/kernel/Terminal/VirtualTTY.cpp | 15 +++++++------- 8 files changed, 36 insertions(+), 27 deletions(-) diff --git a/kernel/include/kernel/Terminal/PseudoTerminal.h b/kernel/include/kernel/Terminal/PseudoTerminal.h index 731ecd4559..29d80e82a9 100644 --- a/kernel/include/kernel/Terminal/PseudoTerminal.h +++ b/kernel/include/kernel/Terminal/PseudoTerminal.h @@ -20,7 +20,7 @@ namespace Kernel BAN::ErrorOr ptsname(); - void putchar(uint8_t ch); + bool putchar(uint8_t ch); protected: BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; @@ -61,7 +61,7 @@ namespace Kernel void clear() override; protected: - void putchar_impl(uint8_t ch) override; + bool putchar_impl(uint8_t ch) override; BAN::ErrorOr ioctl_impl(int, void*) override; diff --git a/kernel/include/kernel/Terminal/Serial.h b/kernel/include/kernel/Terminal/Serial.h index 14a80bca6f..ce1d6f8cd3 100644 --- a/kernel/include/kernel/Terminal/Serial.h +++ b/kernel/include/kernel/Terminal/Serial.h @@ -53,7 +53,7 @@ namespace Kernel protected: virtual BAN::StringView name() const override { return m_name; } - virtual void putchar_impl(uint8_t) override; + virtual bool putchar_impl(uint8_t) override; private: SerialTTY(Serial); diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index bf2749b81f..d2be6e632e 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -58,14 +58,14 @@ namespace Kernel protected: TTY(mode_t mode, uid_t uid, gid_t gid); - virtual void putchar_impl(uint8_t ch) = 0; + virtual bool putchar_impl(uint8_t ch) = 0; virtual void update_cursor() {} virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override; private: - void putchar(uint8_t ch); + bool putchar(uint8_t ch); void do_backspace(); protected: diff --git a/kernel/include/kernel/Terminal/VirtualTTY.h b/kernel/include/kernel/Terminal/VirtualTTY.h index f2e40afcab..d4f3cf0211 100644 --- a/kernel/include/kernel/Terminal/VirtualTTY.h +++ b/kernel/include/kernel/Terminal/VirtualTTY.h @@ -26,7 +26,7 @@ namespace Kernel protected: virtual BAN::StringView name() const override { return m_name; } - virtual void putchar_impl(uint8_t ch) override; + virtual bool putchar_impl(uint8_t ch) override; void update_cursor() override; private: diff --git a/kernel/kernel/Terminal/PseudoTerminal.cpp b/kernel/kernel/Terminal/PseudoTerminal.cpp index 6f2428b47d..a6b78ecba5 100644 --- a/kernel/kernel/Terminal/PseudoTerminal.cpp +++ b/kernel/kernel/Terminal/PseudoTerminal.cpp @@ -85,16 +85,19 @@ namespace Kernel return BAN::Error::from_errno(ENODEV); } - void PseudoTerminalMaster::putchar(uint8_t ch) + bool PseudoTerminalMaster::putchar(uint8_t ch) { SpinLockGuard _(m_buffer_lock); - reinterpret_cast(m_buffer->vaddr())[(m_buffer_tail + m_buffer_size) % m_buffer->size()] = ch; + if (m_buffer_size >= m_buffer->size()) + return false; - if (m_buffer_size < m_buffer->size()) - m_buffer_size++; - else - m_buffer_tail = (m_buffer_tail + 1) % m_buffer->size(); + reinterpret_cast(m_buffer->vaddr())[(m_buffer_tail + m_buffer_size) % m_buffer->size()] = ch; + m_buffer_size++; + + m_buffer_blocker.unblock(); + + return true; } BAN::ErrorOr PseudoTerminalMaster::read_impl(off_t, BAN::ByteSpan buffer) @@ -166,10 +169,11 @@ namespace Kernel (void)write_impl(0, BAN::ConstByteSpan::from(message)); } - void PseudoTerminalSlave::putchar_impl(uint8_t ch) + bool PseudoTerminalSlave::putchar_impl(uint8_t ch) { if (auto master = m_master.lock()) - master->putchar(ch); + return master->putchar(ch); + return false; } BAN::ErrorOr PseudoTerminalSlave::ioctl_impl(int request, void* argument) diff --git a/kernel/kernel/Terminal/Serial.cpp b/kernel/kernel/Terminal/Serial.cpp index f00bb3d3d3..bcc68831eb 100644 --- a/kernel/kernel/Terminal/Serial.cpp +++ b/kernel/kernel/Terminal/Serial.cpp @@ -258,9 +258,10 @@ namespace Kernel return m_serial.height(); } - void SerialTTY::putchar_impl(uint8_t ch) + bool SerialTTY::putchar_impl(uint8_t ch) { m_serial.putchar(ch); + return true; } } diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index e99b5d7824..4f3bcb1b81 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -327,11 +327,12 @@ namespace Kernel } } - void TTY::putchar(uint8_t ch) + bool TTY::putchar(uint8_t ch) { SpinLockGuard _(m_write_lock); if (m_tty_ctrl.draw_graphics) - putchar_impl(ch); + return putchar_impl(ch); + return true; } BAN::ErrorOr TTY::read_impl(off_t, BAN::ByteSpan buffer) @@ -365,10 +366,12 @@ namespace Kernel BAN::ErrorOr TTY::write_impl(off_t, BAN::ConstByteSpan buffer) { SpinLockGuard _(m_write_lock); - for (size_t i = 0; i < buffer.size(); i++) - putchar(buffer[i]); + size_t written = 0; + for (; written < buffer.size(); written++) + if (!putchar(buffer[written])) + break; update_cursor(); - return buffer.size(); + return written; } void TTY::putchar_current(uint8_t ch) diff --git a/kernel/kernel/Terminal/VirtualTTY.cpp b/kernel/kernel/Terminal/VirtualTTY.cpp index 4f60d5346e..f11a229009 100644 --- a/kernel/kernel/Terminal/VirtualTTY.cpp +++ b/kernel/kernel/Terminal/VirtualTTY.cpp @@ -501,7 +501,7 @@ namespace Kernel scroll_if_needed(); } - void VirtualTTY::putchar_impl(uint8_t ch) + bool VirtualTTY::putchar_impl(uint8_t ch) { ASSERT(m_write_lock.current_processor_has_lock()); @@ -531,10 +531,10 @@ namespace Kernel { reset_ansi(); dprintln_if(DEBUG_VTTY, "invalid utf8"); - return; + return true; } m_state = State::WaitingUTF8; - return; + return true; case State::WaitingAnsiEscape: if (ch == CSI) m_state = State::WaitingAnsiCSI; @@ -543,21 +543,21 @@ namespace Kernel reset_ansi(); dprintln_if(DEBUG_VTTY, "unsupported byte after ansi escape {2H}", (uint8_t)ch); } - return; + return true; case State::WaitingAnsiCSI: handle_ansi_csi(ch); - return; + return true; case State::WaitingUTF8: if ((ch & 0xC0) != 0x80) { m_state = State::Normal; dprintln_if(DEBUG_VTTY, "invalid utf8"); - return; + return true; } m_utf8_state.codepoint = (m_utf8_state.codepoint << 6) | (ch & 0x3F); m_utf8_state.bytes_missing--; if (m_utf8_state.bytes_missing) - return; + return true; m_state = State::Normal; codepoint = m_utf8_state.codepoint; break; @@ -566,6 +566,7 @@ namespace Kernel } putcodepoint(codepoint); + return true; } void VirtualTTY::update_cursor()