Kernel/TTY: Support non-blocking reads with termios VMIN == 0

In a TTY's non-canonical mode, data availability can be configured by
setting VMIN and VTIME to determine the minimum amount of bytes to read
and the timeout between bytes, respectively. Some ports (such as SRB2)
set VMIN to 0 which effectively makes reading a TTY such as stdin a
non-blocking read. We didn't support this, causing ports to hang as soon
as they try to read stdin without any data available.

Add a very duct-tapey implementation for the case where VMIN == 0 by
overwriting the TTY's description's blocking status; 3 FIXMEs are
included to make sure we clean this up some day.
This commit is contained in:
Jelle Raaijmakers 2024-02-13 00:16:49 +01:00 committed by Andreas Kling
parent 877641f626
commit 96675e61cd
2 changed files with 9 additions and 4 deletions

View file

@ -373,7 +373,7 @@ void TTY::flush_input()
evaluate_block_conditions();
}
ErrorOr<void> TTY::set_termios(termios const& t)
ErrorOr<void> TTY::set_termios(OpenFileDescription& description, termios const& t)
{
ErrorOr<void> rc;
m_termios = t;
@ -463,10 +463,15 @@ ErrorOr<void> TTY::set_termios(termios const& t)
}
}
// FIXME: decouple VMIN/VTIME support from the description's blocking status
// FIXME: support VMIN > 1 where we should block until VMIN characters are available
// FIXME: implement support for VTIME as an interbyte timeout
description.set_blocking(in_canonical_mode() || m_termios.c_cc[VMIN] > 0);
return rc;
}
ErrorOr<void> TTY::ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg)
ErrorOr<void> TTY::ioctl(OpenFileDescription& description, unsigned request, Userspace<void*> arg)
{
auto& current_process = Process::current();
TRY(current_process.require_promise(Pledge::tty));
@ -520,7 +525,7 @@ ErrorOr<void> TTY::ioctl(OpenFileDescription&, unsigned request, Userspace<void*
case TCSETSW: {
auto user_termios = static_ptr_cast<termios const*>(arg);
auto termios = TRY(copy_typed_from_user(user_termios));
auto rc = set_termios(termios);
auto rc = set_termios(description, termios);
if (request == TCSETSF)
flush_input();
return rc;

View file

@ -37,7 +37,6 @@ public:
return 0;
}
ErrorOr<void> set_termios(termios const&);
bool should_generate_signals() const { return (m_termios.c_lflag & ISIG) == ISIG; }
bool should_flush_on_signal() const { return (m_termios.c_lflag & NOFLSH) != NOFLSH; }
bool should_echo_input() const { return (m_termios.c_lflag & ECHO) == ECHO; }
@ -78,6 +77,7 @@ private:
virtual bool is_tty() const final override { return true; }
virtual void echo(u8) = 0;
ErrorOr<void> set_termios(OpenFileDescription&, termios const&);
template<typename Functor>
void process_output(u8, Functor put_char);