Skip to content

Commit

Permalink
Fix pipe hang (issue #319)
Browse files Browse the repository at this point in the history
This issue turned out to be a kernel bug which has been fixed in:
torvalds/linux@46a525e

Reported here:
axboe/liburing#665 (comment)

We can workaround it by making sure pipes are non-blocking, uring considers
pipes unbounded work and relies on uring worker threads if they are blocking,
the bug is only triggered if this is the case, so force them to be non-blocking.

If we use splice, the splice call itself needs the worker threads and the bug
surfaces again (I verified this with perf probes), so disable splice for now.
Even with the fix, it's desirable to keep pipes as non-blocking to avoid thread
pooling.

The splice call can return EAGAIN in uring, this happens even with the kernel
patched, so handle it for the future.

We can tune this better by disabling splice only for the unpatched kernels.
  • Loading branch information
haesbaert committed Oct 20, 2022
1 parent 2437787 commit a702def
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion lib_eio_linux/eio_linux.ml
Original file line number Diff line number Diff line change
Expand Up @@ -953,16 +953,20 @@ let fast_copy src dst =
with End_of_file -> ()

(* Try a fast copy using splice. If the FDs don't support that, switch to copying. *)
let fast_copy_try_splice src dst =
let _fast_copy_try_splice src dst =
try
while true do
let _ : int = Low_level.splice src ~dst ~len:max_int in
()
done
with
| End_of_file -> ()
| Unix.Unix_error (Unix.EAGAIN, "splice", _) -> fast_copy src dst
| Unix.Unix_error (Unix.EINVAL, "splice", _) -> fast_copy src dst

(* XXX workaround for issue #319, PR #327 *)
let fast_copy_try_splice src dst = fast_copy src dst

(* Copy using the [Read_source_buffer] optimisation.
Avoids a copy if the source already has the data. *)
let copy_with_rsb rsb dst =
Expand Down Expand Up @@ -1290,6 +1294,9 @@ let stdenv ~run_event_loop =

let pipe sw =
let r, w = Unix.pipe () in
(* XXX workaround for issue #319, PR #327 *)
Unix.set_nonblock r;
Unix.set_nonblock w;
let r = source (FD.of_unix ~sw ~seekable:false ~close_unix:true r) in
let w = sink (FD.of_unix ~sw ~seekable:false ~close_unix:true w) in
r, w
Expand Down

0 comments on commit a702def

Please sign in to comment.