Skip to content

Commit

Permalink
eio_posix: fix pread at end-of-file
Browse files Browse the repository at this point in the history
Reported by Simon Grondin.
  • Loading branch information
talex5 committed Jul 11, 2023
1 parent 57ace76 commit 38d9799
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
6 changes: 5 additions & 1 deletion lib_eio_posix/flow.ml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ let of_fd fd = object (_ : <Eio_unix.Net.stream_socket; Eio.File.rw>)
method read_methods = []
method copy src = copy src fd

method pread ~file_offset bufs = Low_level.preadv ~file_offset fd (Array.of_list bufs)
method pread ~file_offset bufs =
let got = Low_level.preadv ~file_offset fd (Array.of_list bufs) in
if got = 0 then raise End_of_file
else got

method pwrite ~file_offset bufs = Low_level.pwritev ~file_offset fd (Array.of_list bufs)

method stat = fstat fd
Expand Down
6 changes: 5 additions & 1 deletion lib_eio_windows/flow.ml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ let of_fd fd = object (_ : <Eio_unix.Net.stream_socket; Eio.File.rw>)
method read_methods = []
method copy src = copy src fd

method pread ~file_offset bufs = Low_level.preadv ~file_offset fd (Array.of_list bufs)
method pread ~file_offset bufs =
let got = Low_level.preadv ~file_offset fd (Array.of_list bufs) in
if got = 0 then raise End_of_file
else got

method pwrite ~file_offset bufs = Low_level.pwritev ~file_offset fd (Array.of_list bufs)

method stat = fstat fd
Expand Down
21 changes: 21 additions & 0 deletions tests/fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,27 @@ Check reading and writing vectors at arbitrary offsets:
- : unit = ()
```

Reading at the end of a file:

```ocaml
# run @@ fun env ->
let cwd = Eio.Stdenv.cwd env in
let path = cwd / "test.txt" in
Path.with_open_out path ~create:(`Or_truncate 0o600) @@ fun file ->
Eio.Flow.copy_string "abc" file;
let buf = Cstruct.create 10 in
let got = Eio.File.pread file [buf] ~file_offset:(Int63.of_int 0) in
traceln "Read %S" (Cstruct.to_string buf ~len:got);
try
ignore (Eio.File.pread file [buf] ~file_offset:(Int63.of_int 3) : int);
assert false
with End_of_file ->
traceln "End-of-file";;
+Read "abc"
+End-of-file
- : unit = ()
```

# Cancelling while readable

Ensure reads can be cancelled promptly, even if there is no need to wait:
Expand Down

0 comments on commit 38d9799

Please sign in to comment.