eio_luv: allow Net.connect to be cancelled#311
Conversation
|
I think we have to call the #include <stdio.h>
#include <stdlib.h>
#include <uv.h>
static void
on_connect_cb(uv_connect_t *uv_connect, int status)
{
printf("%s: %p status=%d (%s)\n", __func__, uv_connect, status, uv_strerror(status));
}
static void
on_timer_cb(uv_timer_t *uv_timer)
{
uv_tcp_t *uv_socket = uv_handle_get_data((uv_handle_t *)uv_timer);
printf("%s: uv_timer=%p uv_socket=%p\n", __func__, uv_socket,
uv_socket);
uv_close((uv_handle_t *)uv_socket, (uv_close_cb)NULL);
}
int
main(void)
{
uv_loop_t *loop = uv_default_loop();
uv_tcp_t uv_socket;
uv_connect_t uv_connect;
struct sockaddr_in sin;
uv_timer_t uv_timer;
uv_tcp_init(loop, &uv_socket);
uv_ip4_addr("142.250.186.174", 8080, &sin);
uv_tcp_connect(&uv_connect, &uv_socket, (const struct sockaddr *)&sin,
on_connect_cb);
uv_timer_init(loop, &uv_timer);
uv_handle_set_data((uv_handle_t *)&uv_timer, &uv_socket);
uv_timer_start(&uv_timer, on_timer_cb, 1000, 0);
printf("Default loop.\n");
uv_run(loop, UV_RUN_DEFAULT);
uv_loop_close(loop);
return (0);
}This seems to be correct as the callback is called with UV_CANCELED: |
|
The manual describes the semantics: |
lib_eio_luv/eio_luv.ml
Outdated
| Fiber_context.set_cancel_fn k.fiber (fun _ex -> | ||
| match to_unix_opt `Peek sock with | ||
| | Some fd -> Unix.shutdown fd Unix.SHUTDOWN_ALL | ||
| | None -> () | ||
| ) |
There was a problem hiding this comment.
| Fiber_context.set_cancel_fn k.fiber (fun _ex -> | |
| match to_unix_opt `Peek sock with | |
| | Some fd -> Unix.shutdown fd Unix.SHUTDOWN_ALL | |
| | None -> () | |
| ) | |
| Fiber_context.set_cancel_fn k.fiber (fun _ex -> Handle.close sock) |
lib_eio_luv/eio_luv.ml
Outdated
| | None -> () | ||
| ) | ||
| with ex -> | ||
| Handle.close sock; |
There was a problem hiding this comment.
| Handle.close sock; | |
| Handle.ensure_closed sock; |
e14c6ef to
5126b3a
Compare
|
@haesbaert : that sounds good. However, the tests hang if I do that! I moved things around a bit and added a commented-out close call. Does it work for you if you uncomment it and do |
You're right, and no, it's still hangs with/without the commented line :( |
|
I noticed that |
|
Yeah, I'm not sure why the tests hang. Would be good to find out. It would also be good to make it easier to find out, maybe by improving MDX, or by having Eio dump out some state on a signal or something. If you do If you can capture a hanging case with |
|
Did some minor digging, it's not in MDX, it seems to hang on (* Write a string to a pipe and read it out again. *)
let test_copy () =
Printf.eprintf "COPY A\n";
Eio_linux.run ~queue_depth:3 @@ fun _stdenv ->
Switch.run @@ fun sw ->
Printf.eprintf "COPY B\n";
let msg = "Hello!" in
let from_pipe, to_pipe = Eio_linux.pipe sw in
let buffer = Buffer.create 20 in
Printf.eprintf "COPY C\n";
Fiber.both
(fun () ->
Printf.eprintf "COPY D1\n";
Eio.Flow.copy from_pipe (Eio.Flow.buffer_sink buffer); (* XXXXX hangs here XXXXX *)
Printf.eprintf "COPY D1A\n";
)
(fun () ->
Printf.eprintf "COPY D2\n";
Eio.Flow.copy (Eio.Flow.string_source msg) to_pipe;
Printf.eprintf "COPY D2A\n";
Eio.Flow.copy (Eio.Flow.string_source msg) to_pipe;
Eio.Flow.close to_pipe;
Printf.eprintf "COPY D2B\n";
);
Printf.eprintf "COPY D3\n";
Alcotest.(check string) "Copy correct" (msg ^ msg) (Buffer.contents buffer);
Printf.eprintf "COPY D4\n";
Eio.Flow.close from_pipe;
Printf.eprintf "COPY D5\n";
Printf.eprintf "\nCOPY FINISHED!!!\n\n"gives: I'm running Funny thing is I can't trigger with |
|
Be carefuil: You can use |
Ah yes, stupid me, I automatically assumed that |
|
That is odd! What happens if you just run |
|
Given that the test hang is in code not affected by this (eio_luv) PR, and was occurring before, I propose to merge this as-is and open a new issue for the eio_linux test hang. |
Yes please, sorry I got sidetracked. |
Fixes ocaml-multicore#303. Reported by Nicolás Ojeda Bär.
5126b3a to
9cf532b
Compare
CHANGES: Changes: - Update to OCaml 5.0.0~beta1 (@anmonteiro @talex5 ocaml-multicore/eio#346). - Add API for seekable read/writes (@nojb ocaml-multicore/eio#307). - Add `Flow.write` (@haesbaert ocaml-multicore/eio#318). This provides an optimised alternative to `copy` in the case where you are writing from a buffer. - Add `Net.with_tcp_connect` (@bikallem ocaml-multicore/eio#302). Convenience function for opening a TCP connection. - Add `Eio.Time.Timeout` (@talex5 ocaml-multicore/eio#320). Makes it easier to pass timeouts around. - Add `Eio_mock.Clock` (@talex5 ocaml-multicore/eio#328). Control time in tests. - Add `Buf_read.take_while1` and `skip_while1` (@bikallem ocaml-multicore/eio#309). These fail if no characters match. - Make the type parameter for `Promise.t` covariant (@anmonteiro ocaml-multicore/eio#300). - Move list functions into a dedicated submodule (@raphael-proust ocaml-multicore/eio#315). - Direct implementation of `Flow.source_string` (@c-cube ocaml-multicore/eio#317). Slightly faster. Bug fixes: - `Condition.broadcast` must interlock as well (@haesbaert ocaml-multicore/eio#324). - Split the reads into no more than 2^32-1 for luv (@haesbaert @talex5 @EduardoRFS ocaml-multicore/eio#343). Luv uses a 32 bit int for buffer sizes and wraps if the value passed is too big. - eio_luv: allow `Net.connect` to be cancelled (@talex5 @nojb ocaml-multicore/eio#311). - eio_main: Use dedicated log source (@anmonteiro ocaml-multicore/eio#326). - linux_eio: fix kernel version number in log message (@talex5 @nojb ocaml-multicore/eio#314). - Account for stack differences in the socketpair test (issue ocaml-multicore/eio#312) (@haesbaert ocaml-multicore/eio#313). Documentation: - Add Best Practices section to README (@talex5 ocaml-multicore/eio#299). - Documentation improvements (@talex5 ocaml-multicore/eio#295 ocaml-multicore/eio#337).
Fixes #303.
/cc @haesbaert @nojb