eio icon indicating copy to clipboard operation
eio copied to clipboard

Eio.Path.load doesn't work for files in /proc (which don't report their size in stat)

Open copy opened this issue 9 months ago • 4 comments

To reproduce:

utop [1]: #require "eio_posix";;
utop [2]: open Eio.Path;;
utop [3]: Eio_posix.run (fun env -> Eio.Path.load (env#fs / "/proc/loadavg"));;
val _5 : string = ""

copy avatar Feb 27 '25 16:02 copy

Thanks for the report @copy ! It appear the issue here is that load does a Eio.File.size and uses that to create an internal buffer to read into. The files in proc aren't really "real" so have a 0 file size which is leading to this problem.

I think the right approach here would be to document this limitation of Eio.Path.load and in this case to explicitly collect the data? Maybe something like:

  Eio_posix.run @@ fun env ->
  let loadavg =
    let buf = Buffer.create 128 in
    Eio.Path.with_open_in (env#fs / "/proc/loadavg") @@ fun src ->
    Eio.Flow.copy src (Eio.Flow.buffer_sink buf);
    Buffer.contents buf
  in
  Eio.traceln "loadavg: %s" loadavg

Alternatively we could update the implementation of load to not check the size of the file before trying to read it.

patricoferris avatar Mar 01 '25 15:03 patricoferris

((Only after writing all of that did I see your comment in parentheses ^^"))

patricoferris avatar Mar 01 '25 15:03 patricoferris

We already have:

  let read_all flow =
    Buf_read.(parse_exn take_all) flow ~max_size:max_int

Perhaps if size = 0 then read_all flow would do here?

talex5 avatar Mar 01 '25 15:03 talex5

Perhaps if size = 0 then read_all flow would do here?

Alternatively, we could do a 1-byte read and if it doesn't return eof, continue reading until eof. That has the advantage of being more robust against other stat problems, at the cost of an extra syscall.

copy avatar Mar 02 '25 09:03 copy