lwt icon indicating copy to clipboard operation
lwt copied to clipboard

Windows Unix.select bug impacts Lwt_engine.select

Open gabelevi opened this issue 7 years ago • 1 comments

I had previously run into a bug with Unix.select on Windows, but I only just reported it: https://caml.inria.fr/mantis/view.php?id=7665

Long story short, when you have a fd set which is a mix of sockets and non-sockets, sometimes some fds are not reported as being ready even though they are totally ready.

Personally, I'm working around this by replacing the engine like so

class windows_select = object
  inherit Lwt_engine.select_based

  method private select fds_r fds_w timeout =
    (* Figure out which fds are already ready to be read *)
    let ready_r = List.fold_left (fun ready_r fd_r ->
      match Unix.select [fd_r] [] [] 0.0 with
      | [], _, _ -> ready_r
      | _ -> fd_r::ready_r
    ) [] fds_r in

    (* Figure out which fds are already ready to be written *)
    let ready_w = List.fold_left (fun ready_w fd_w ->
      match Unix.select [] [fd_w] [] 0.0 with
      | _, [], _ -> ready_w
      | _ -> fd_w::ready_w
    ) [] fds_w in

    (* If nothing is ready, then do a multi-fd select with the timeout *)
    if ready_r = [] && ready_w = []
    then
      let fds_r, fds_w, _ = Unix.select fds_r fds_w [] timeout in
      (fds_r, fds_w)
    else (ready_r, ready_w)
end
...
if Sys.win32 then Lwt_engine.set (new windows_select);

gabelevi avatar Nov 02 '17 18:11 gabelevi

Thanks for the link. I understand that this is a bug in OCaml's Unix library rather than Lwt, but, indeed, it would be nice if Lwt did the right thing anyway :) At least, having this here helps people find a workaround, while we figure out what to do.

aantron avatar Nov 02 '17 19:11 aantron