Skip to content

Commit

Permalink
eio_windows: unregister FDs on cancel
Browse files Browse the repository at this point in the history
This was fixed in cc19aa1 for `eio_posix`, but not for
`eio_windows`.

The error looks like:

    exception Unix.Unix_error(Unix.ENOTSOCK, "select", "")
  • Loading branch information
talex5 committed Sep 29, 2024
1 parent 424f5e8 commit 7e7ce6a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 2 deletions.
6 changes: 6 additions & 0 deletions lib_eio_posix/test/dune
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@
(package eio_posix)
(build_if (= %{os_type} "Unix"))
(libraries eio_posix))

(test
(name test_await)
(package eio_posix)
(build_if (= %{os_type} "Unix"))
(libraries eio_posix))
25 changes: 25 additions & 0 deletions lib_eio_posix/test/test_await.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
open Eio.Std

let () =
Eio_posix.run @@ fun _ ->
let a, b = Unix.(socketpair PF_UNIX SOCK_STREAM 0) in
(* Start awaiting readable/writable state, but cancel immediately. *)
try
Eio.Cancel.sub (fun cc ->
Fiber.all [
(fun () -> Eio_unix.await_readable a);
(fun () -> Eio_unix.await_writable b);
(fun () -> Eio.Cancel.cancel cc Exit);
];
assert false
)
with Eio.Cancel.Cancelled _ ->
(* Now wait for something else. Will fail if the old FDs are still being waited on. *)
let c, d = Unix.(socketpair PF_UNIX SOCK_STREAM 0) in
Unix.close a;
Unix.close b;
Fiber.first
(fun () -> Eio_unix.await_readable c)
(fun () -> Eio_unix.await_writable d);
Unix.close c;
Unix.close d
4 changes: 4 additions & 0 deletions lib_eio_windows/sched.ml
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ let await_readable t (k : unit Suspended.t) fd =
if was_empty then update t waiters fd;
Fiber_context.set_cancel_fn k.fiber (fun ex ->
Lwt_dllist.remove node;
if Lwt_dllist.is_empty waiters.read then
update t waiters fd;
t.active_ops <- t.active_ops - 1;
enqueue_failed_thread t k ex
);
Expand All @@ -287,6 +289,8 @@ let await_writable t (k : unit Suspended.t) fd =
if was_empty then update t waiters fd;
Fiber_context.set_cancel_fn k.fiber (fun ex ->
Lwt_dllist.remove node;
if Lwt_dllist.is_empty waiters.write then
update t waiters fd;
t.active_ops <- t.active_ops - 1;
enqueue_failed_thread t k ex
);
Expand Down
36 changes: 34 additions & 2 deletions lib_eio_windows/test/test.ml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
open Eio.Std

module Timeout = struct
let test clock () =
let t0 = Unix.gettimeofday () in
Expand Down Expand Up @@ -48,6 +50,35 @@ module Dla = struct
]
end

module Await_fd = struct
let test_cancel () =
let a, b = Unix.(socketpair PF_UNIX SOCK_STREAM 0) in
(* Start awaiting readable/writable state, but cancel immediately. *)
try
Eio.Cancel.sub (fun cc ->
Fiber.all [
(fun () -> Eio_unix.await_readable a);
(fun () -> Eio_unix.await_writable b);
(fun () -> Eio.Cancel.cancel cc Exit);
];
assert false
)
with Eio.Cancel.Cancelled _ ->
(* Now wait for something else. Will fail if the old FDs are still being waited on. *)
let c, d = Unix.(socketpair PF_UNIX SOCK_STREAM 0) in
Unix.close a;
Unix.close b;
Fiber.first
(fun () -> Eio_unix.await_readable c)
(fun () -> Eio_unix.await_writable d);
Unix.close c;
Unix.close d

let tests = [
"cancel", `Quick, test_cancel;
]
end


let () =
Eio_windows.run @@ fun env ->
Expand All @@ -56,5 +87,6 @@ let () =
"fs", Test_fs.tests env;
"timeout", Timeout.tests env;
"random", Random.tests env;
"dla", Dla.tests
]
"dla", Dla.tests;
"await", Await_fd.tests;
]

0 comments on commit 7e7ce6a

Please sign in to comment.