Project

General

Profile

Actions

Bug #18881

closed

IO#read_nonblock raises IOError when called following buffered character IO

Added by javanthropus (Jeremy Bopp) about 1 month ago. Updated about 1 month ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x64-mingw-ucrt]
[ruby-core:109055]

Description

The following example code works as expected on Linux but raises an IOError on Windows:

r, w = IO.pipe
w.write("foobar")
c = r.getc
r.ungetc(c)
r.read_nonblock(3)

The error message is:

IOError: byte oriented read for character buffered IO

Updated by shyouhei (Shyouhei Urabe) about 1 month ago

Not looking at the implementation but sounds like an issue of Linux side to me. The error message seems intentional.

Updated by nobu (Nobuyoshi Nakada) about 1 month ago

  • Status changed from Open to Rejected

It is an expected behavior.
On Windows, text/binary conversion is used by default, and ungetc pushes back the character to the conversion buffer in that case.
The error message means this situation.

Updated by shyouhei (Shyouhei Urabe) about 1 month ago

@nobu (Nobuyoshi Nakada) Yes but wouldn't it be nice if IO#read_nonblock also raises on Linux?

Updated by nobu (Nobuyoshi Nakada) about 1 month ago

@shyouhei (Shyouhei Urabe) Even without any conversion?

This is an example on macOS.

$ ruby -v -e 'r, w = IO.pipe; r.set_encoding("utf-8", "iso-8859-15"); w.write("foobar"); c = r.getc; r.ungetc(c); r.read_nonblock(3)'
ruby 3.2.0dev (2022-06-28T06:49:05Z master 98bf8c83fa) [x86_64-darwin21]
<internal:io>:63:in `read_nonblock': byte oriented read for character buffered IO (IOError)
	from -e:1:in `<main>'
Actions #5

Updated by shyouhei (Shyouhei Urabe) about 1 month ago

nobu (Nobuyoshi Nakada) wrote in #note-4:

@shyouhei (Shyouhei Urabe) Even without any conversion?

Yes. "Byte oriented and character oriented IO operations cannot be mixed at all" sounds much simpler than the current (it sometimes raises and sometimes doesn't).

Updated by nobu (Nobuyoshi Nakada) about 1 month ago

Do you mean that once character oriented methods are called, all byte oriented methods always fail?
(Possibly reset by seek?)

Updated by shyouhei (Shyouhei Urabe) about 1 month ago

Basically yes. Some edge cases can be considered though (e.g. IO#flush could also reset this, IO#pread could be special-case allowed (avoiding IO#seek is the reason for this method to exist), etc).

Updated by javanthropus (Jeremy Bopp) about 1 month ago

There needs to be documentation to cover the corner cases no matter what. Wouldn't it be better to document the current behavior rather than add artificial limitations?

For what it's worth, I was able to reproduce the reported behavior on Linux with a minor modification to the example script:

r, w = IO.pipe
r.set_encoding('utf-8', universal_newline: true)  # Set line ending handling like on Windows
w.write("foobar")
c = r.getc
r.ungetc(c)
r.read_nonblock(3)
Actions

Also available in: Atom PDF