Re: [RFC] Io\Terminal

From: Date: Sat, 24 Oct 2026 17:12:25 +0000
Subject: Re: [RFC] Io\Terminal
References: 1 2 3  Groups: php.internals 
Request: Send a blank email to internals+get-132916@lists.php.net to get a copy of this message
Hi Sjoerd, I've pushed fixes for the issues you pointed out, along with regression tests. Zero-timeout reads now handle already-available escape sequences without waiting, and getSize() no longer suppresses a pending resize notification. While testing, I also found that incomplete UTF-8 at EOF could cause readKey() to keep returning null. It now throws TerminalException on EOF, while genuine timeouts still preserve the partial bytes. https://github.com/php/php-src/pull/23941 Thanks again for the careful review. Regards, Pratik On Fri, 23 Oct 2026 16:44:51 -0700, Pratik Bhujel <prateekbhujelpb@gmail.com> wrote: > Hi Sjoerd, > > Thanks for taking a look. > Perhaps it would be desirable to distinguish between the user cancelling, and a genuine error, > and perhaps also EOF; for example with subclasses of TerminalException. > Yes, I see the use case. An application may handle a cancelled password prompt quietly but > report an I/O failure. Currently they all throw TerminalException, and the messages are not stable > identifiers. Separate subclasses would allow that distinction while keeping TerminalException as the > common catch. I would like to settle this before the vote. > Is this sufficiently long, even when used over SSH or such? Is this configurable in readSecret > as well? > The 25 ms starts after Escape arrives, so it is not a limit on the SSH round trip. Delayed > fragments can still exceed it. readKey() lets you increase sequenceTimeout, within the overall > timeout. > > readSecret() currently uses a fixed 25 ms wait in its byte-stream escape handling. It is not > separately configurable, and increasing the overall timeout does not increase that wait. That is a > limitation worth addressing. Native Windows console input uses input records, so this > escape-sequence timing does not apply there. > If I resize the terminal twice, do I get two Key::Resize? getSize() seems to update the stored > size of the terminal. Do I still get a Key::Resize after I call getSize()? > Not necessarily two. On POSIX, resize notifications can be coalesced, and changes between reads > can be detected by comparing dimensions. > > You are right about getSize(). It updates the same cached dimensions, so calling it first can > hide a change from that comparison. Windows can still have queued resize records. I think getSize() > should query the size without acknowledging a pending notification. That needs fixing and > documenting. Resize should mean "check the current size", rather than promise a count of > every resize. > This would not work with escape sequences, right? Or does it work correctly if the key is > already buffered? > Reading the current byte-stream decoder, the zero deadline makes it return Escape before > checking the remaining bytes, even if the whole sequence is buffered. The focused zero-timeout test > covers a lone Escape. > > Zero should prevent waiting while still allowing a complete available sequence to be decoded. > That needs a focused regression test and a fix. > > I’ll follow up with the test results and changes. These findings are from checking the code; > I haven’t run the new reproducers yet. > > Regards, > Pratik

« previous php.internals (#132916) next »