Skip to content

Commit 8364428

Browse files
committed
eio_windows: unregister FDs on cancel
This was fixed in cc19aa1 for `eio_posix`, but not for `eio_windows`. The error looks like: exception Unix.Unix_error(Unix.ENOTSOCK, "select", "")
1 parent d2a3e21 commit 8364428

File tree

4 files changed

+65
-4
lines changed

4 files changed

+65
-4
lines changed

lib_eio_posix/test/dune

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
(enabled_if (= %{os_type} "Unix"))
44
(deps (package eio_posix)))
55

6-
(test
7-
(name open_beneath)
6+
(tests
7+
(names open_beneath test_await)
88
(package eio_posix)
99
(build_if (= %{os_type} "Unix"))
1010
(libraries eio_posix))

lib_eio_posix/test/test_await.ml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
open Eio.Std
2+
3+
let () =
4+
Eio_posix.run @@ fun _ ->
5+
let a, b = Unix.(socketpair PF_UNIX SOCK_STREAM 0) in
6+
(* Start awaiting readable/writable state, but cancel immediately. *)
7+
try
8+
Eio.Cancel.sub (fun cc ->
9+
Fiber.all [
10+
(fun () -> Eio_unix.await_readable a);
11+
(fun () -> Eio_unix.await_writable b);
12+
(fun () -> Eio.Cancel.cancel cc Exit);
13+
];
14+
assert false
15+
)
16+
with Eio.Cancel.Cancelled _ ->
17+
(* Now wait for something else. Will fail if the old FDs are still being waited on. *)
18+
let c, d = Unix.(socketpair PF_UNIX SOCK_STREAM 0) in
19+
Unix.close a;
20+
Unix.close b;
21+
Fiber.first
22+
(fun () -> Eio_unix.await_readable c)
23+
(fun () -> Eio_unix.await_writable d);
24+
Unix.close c;
25+
Unix.close d

lib_eio_windows/sched.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ let await_readable t (k : unit Suspended.t) fd =
271271
if was_empty then update t waiters fd;
272272
Fiber_context.set_cancel_fn k.fiber (fun ex ->
273273
Lwt_dllist.remove node;
274+
if Lwt_dllist.is_empty waiters.read then
275+
update t waiters fd;
274276
t.active_ops <- t.active_ops - 1;
275277
enqueue_failed_thread t k ex
276278
);
@@ -287,6 +289,8 @@ let await_writable t (k : unit Suspended.t) fd =
287289
if was_empty then update t waiters fd;
288290
Fiber_context.set_cancel_fn k.fiber (fun ex ->
289291
Lwt_dllist.remove node;
292+
if Lwt_dllist.is_empty waiters.write then
293+
update t waiters fd;
290294
t.active_ops <- t.active_ops - 1;
291295
enqueue_failed_thread t k ex
292296
);

lib_eio_windows/test/test.ml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
open Eio.Std
2+
13
module Timeout = struct
24
let test clock () =
35
let t0 = Unix.gettimeofday () in
@@ -48,6 +50,35 @@ module Dla = struct
4850
]
4951
end
5052

53+
module Await_fd = struct
54+
let test_cancel () =
55+
let a, b = Unix.(socketpair PF_UNIX SOCK_STREAM 0) in
56+
(* Start awaiting readable/writable state, but cancel immediately. *)
57+
try
58+
Eio.Cancel.sub (fun cc ->
59+
Fiber.all [
60+
(fun () -> Eio_unix.await_readable a);
61+
(fun () -> Eio_unix.await_writable b);
62+
(fun () -> Eio.Cancel.cancel cc Exit);
63+
];
64+
assert false
65+
)
66+
with Eio.Cancel.Cancelled _ ->
67+
(* Now wait for something else. Will fail if the old FDs are still being waited on. *)
68+
let c, d = Unix.(socketpair PF_UNIX SOCK_STREAM 0) in
69+
Unix.close a;
70+
Unix.close b;
71+
Fiber.first
72+
(fun () -> Eio_unix.await_readable c)
73+
(fun () -> Eio_unix.await_writable d);
74+
Unix.close c;
75+
Unix.close d
76+
77+
let tests = [
78+
"cancel", `Quick, test_cancel;
79+
]
80+
end
81+
5182

5283
let () =
5384
Eio_windows.run @@ fun env ->
@@ -56,5 +87,6 @@ let () =
5687
"fs", Test_fs.tests env;
5788
"timeout", Timeout.tests env;
5889
"random", Random.tests env;
59-
"dla", Dla.tests
60-
]
90+
"dla", Dla.tests;
91+
"await", Await_fd.tests;
92+
]

0 commit comments

Comments
 (0)