diff --git a/CHANGES.md b/CHANGES.md index 7142bdeaed0..859964cf12f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,8 @@ Unreleased ---------- +- Fix flushing when using `sendfile` fallback (#8288, @alan-j-hu) + - Add `dune show rules` as alias of the `dune rules` command. (#8000, @Alizter) - Fix `%{deps}` to expand properly in `(cat ...)` when containing 2 or more diff --git a/otherlibs/stdune/src/io.ml b/otherlibs/stdune/src/io.ml index 48cbc3e09db..d183f1607dc 100644 --- a/otherlibs/stdune/src/io.ml +++ b/otherlibs/stdune/src/io.ml @@ -145,17 +145,23 @@ module Copyfile = struct | Error `Src_missing -> let message = Printf.sprintf "%s: No such file or directory" src in raise (Sys_error message) - | Ok (src, dst, src_size) -> - Exn.protect - ~f:(fun () -> - try sendfile ~src ~dst src_size - with Unix.Unix_error (EINVAL, "sendfile", _) -> - let ic = Unix.in_channel_of_descr src in - let oc = Unix.out_channel_of_descr dst in - copy_channels ic oc) - ~finally:(fun () -> - Unix.close src; - Unix.close dst) + | Ok (src, dst, src_size) -> ( + let close_fds () = + Unix.close src; + Unix.close dst + in + match sendfile ~src ~dst src_size with + | exception Unix.Unix_error (EINVAL, "sendfile", _) -> + let ic = Unix.in_channel_of_descr src in + let oc = Unix.out_channel_of_descr dst in + Exn.protect + ~f:(fun () -> copy_channels ic oc) + ~finally:(fun () -> + (* we make sure to close the fd's with the channel api to make + sure everything has been flushed *) + close_both (ic, oc)) + | () -> close_fds () + | exception _ -> close_fds ()) let copyfile ?chmod ~src ~dst () = let src_stats = diff --git a/test/blackbox-tests/test-cases/github8041.t b/test/blackbox-tests/test-cases/github8041.t index 357d3969e14..bdb96119cc5 100644 --- a/test/blackbox-tests/test-cases/github8041.t +++ b/test/blackbox-tests/test-cases/github8041.t @@ -30,4 +30,4 @@ larger files. > else > echo "File copied incorrectly" > fi - File copied incorrectly + File copied correctly