Description
We (PSC) have been thinking about the situation created by #20103, with problems reported in #22883 and #23026. A small improvement was made in #22907, and @tonycoz also suggested what he calls an alternative fix (I’ll come to that in a moment) in #23314.
Initially we had thoughts that I posted about, but we now think we were wrong at the time.
We now believe the situation is this:
- The core problem is the fact that I/O functions derive their return code from the filehandle error flag. Instead, they should signal an error only based on the I/O operation they themselves performed, ignoring whether the error flag was already set.
- Back when
readline
was clearing the error flag indiscriminately, the resulting overall behavior tended to incidentally match what would happen if this is how the I/O functions worked, even though they didn’t. - When we changed
readline
to actually be able to signal failures, this charade broke down, and now we are dealing with the fallout from that. The design was broken but held together with chewing gum, and we removed the chewing gum.
As for the error flag, clearly the point of the flag is to preserve error states until they have been dealt with, which that proposal contradicts. Effectively, the error flag exists to prevent data loss in code that is somewhat sloppy (but not too sloppy) in dealing with I/O errors. And because it is a documented interface, we cannot remove it or alter its behavior. Therefore, I/O functions should continue to set and clear it exactly as before, so that user code that was written to examine the flag will continue to behave as it always has. But the functions should entirely ignore the state of the flag in their own operation.
This means we want both #22907 and #23314, plus of course a number of addtional yet-to-be-written changes.
The question now is whether the design of PerlIO even allows for implementing this.
Writing tests for this encountered a problem: read() uses the stream error flag to detect whether an error occurred, the underlying PerlIO_read() behaves like the stdio fread() in that you tell the difference between an error and a short read/eof by checking the stream error or eof flag.
So read() cannot return undef on error unless we do set the error flag. 🙁
I’ll ping @Leont here for another opinion, given he replied that
PerlIO was designed to be an drop-in stdio replacement, instead of being a sensible buffered IO implementation. This is the source of almost all issues in PerlIO.
(Not knowing anything much about the area, I wonder if the envisaged abolition of stdio is useful or even necessary or maybe irrelevant to a bid to do this.)