julia icon indicating copy to clipboard operation
julia copied to clipboard

Should we breathe new life into `readavailable`?

Open jakobnissen opened this issue 8 months ago • 2 comments

The function readavailable is in an awkward position. The documentation says:

Read available buffered data from a stream. Actual I/O is performed only if no data has already been buffered. The result is a Vector{UInt8}.

This makes it sound like it does the following:

  • If data is available in the internal buffer of the IO, read that
  • Else, do one blocking operation to fill the internal buffer and then return whatever you get

This reply implies that that's indeed what it does. It's also what the default definition of write(::IO, ::IO) implies it does

However, in the docstring, the sentence is followed by the warning:

Warning │ │ The amount of data returned is implementation-dependent; for example it can depend on the │ internal choice of buffer size. Other functions such as read should generally be used │ instead.

And the comments in https://github.com/JuliaLang/julia/issues/16821 also implies that this function should not be used at all.

But why? Isn't it quite useful to have a function that reads all the available data? To be sure, I'm a bit bummed out that readavailable doesn't actually read the available bytes, which you would really, really think it did from its name, but apparently also does a blocking operation if that number is zero.

I think it would be nice to either:

  • Clarify that readavailable will return all of the bytes given by bytesavailable if that is nonzero, or else do one blocking read, and will read what becomes available from that, and remove the warning from the docstring, or
  • Slightly change the meaning of readavailable to do what it says on the tin and read exactly the available bytes, no less, no more.

The latter would be nicer, but is slightly breaking and may be too breaking. And maybe there's a reason for the warning?

jakobnissen avatar Apr 02 '25 19:04 jakobnissen

I was quite confused that readavailable is blocking when no bytes are available, and it caused a nasty bug. Let's start by documenting this blocking behaviour?

fonsp avatar Dec 05 '25 15:12 fonsp

Also, the result of bytesavailable does not match the length of readavailable output in this example (Julia 1.12.2):

julia> begin
           cmd = `julia -e "error(123)"`;
           _stdout = Pipe();
           _stderr = Pipe();
           proc = run(
               pipeline(Cmd(
                       cmd;
                       detach=true,
                       windows_hide=true,
                   ), stdout=_stdout, stderr=_stderr),
               wait=false,
           )
           sleep(2)
           @info "result" bytesavailable(_stderr) readavailable(_stderr)
       end
┌ Info: result
│   bytesavailable(_stderr) = 0
│   readavailable(_stderr) =
│    260-element Vector{UInt8}:
│     0x45
│     0x52
│     0x52
│     0x4f
│        ⋮
│     0x35
│     0x30
└     0x0a


fonsp avatar Dec 05 '25 15:12 fonsp