From 3adce92e8a1eeec4f892b0fdb90e617eb3e4cb2f Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Thu, 15 Feb 2024 09:47:07 +0000 Subject: [PATCH] eio_linux: retry openat2 on EAGAIN CI fails sometimes with this error. The man-page says: > the kernel could not ensure that a ".." component didn't escape (due > to a race condition or potential attack). The caller may choose to > retry the openat2() call. --- lib_eio_linux/low_level.ml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/lib_eio_linux/low_level.ml b/lib_eio_linux/low_level.ml index ce3e3df40..9ba42b62f 100644 --- a/lib_eio_linux/low_level.ml +++ b/lib_eio_linux/low_level.ml @@ -270,15 +270,21 @@ let with_chunk ~fallback fn = | None -> fallback () -let openat2 ~sw ?seekable ~access ~flags ~perm ~resolve ?dir path = - let use dir = - let res = Sched.enter "openat2" (enqueue_openat2 (access, flags, perm, resolve, dir, path)) in +let rec openat2 ~sw ?seekable ~access ~flags ~perm ~resolve ?dir path = + let use dir_opt = + let res = Sched.enter "openat2" (enqueue_openat2 (access, flags, perm, resolve, dir_opt, path)) in if res < 0 then ( Switch.check sw; (* If cancelled, report that instead. *) - raise @@ Err.wrap_fs (Uring.error_of_errno res) "openat2" "" - ); - let fd : Unix.file_descr = Obj.magic res in - Fd.of_unix ~sw ?seekable ~close_unix:true fd + match Uring.error_of_errno res with + | EAGAIN -> + (* Linux can return this due to a concurrent update. + It also seems to happen sometimes with no concurrent updates. *) + openat2 ~sw ?seekable ~access ~flags ~perm ~resolve ?dir path + | e -> raise @@ Err.wrap_fs e "openat2" "" + ) else ( + let fd : Unix.file_descr = Obj.magic res in + Fd.of_unix ~sw ?seekable ~close_unix:true fd + ) in match dir with | None -> use None