Description
OCaml signal handlers can't run at any time (unlike C ones). So when an OCaml signal occurs, OCaml just records the fact and runs them at the next safe point. Typically the system call that was running will return with EINTR, the C stub will call caml_leave_blocking_section
, and the signal handler will then run.
This works fine with ocaml-uring. However, libuv automatically retries on EINTR, without giving OCaml a chance to do anything.
This is really a problem with luv, but we might want to make some kind of work-around. libuv does provide its own signal handling system (using handlers written in C to wake the libuv loop).
Reacquiring the runtime lock briefly in e.g. libuv's epoll.c fixes it. However, that would prevent using the system version of libuv.
diff --git a/src/unix/epoll.c b/src/unix/epoll.c
index 97348e25..cc272d64 100644
--- a/src/unix/epoll.c
+++ b/src/unix/epoll.c
@@ -24,6 +24,9 @@
#include <errno.h>
#include <sys/epoll.h>
+void caml_enter_blocking_section (void);
+void caml_leave_blocking_section (void);
+
int uv__epoll_init(uv_loop_t* loop) {
int fd;
fd = epoll_create1(O_CLOEXEC);
@@ -288,6 +291,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
reset_timeout = 0;
}
+ caml_leave_blocking_section();
+ caml_enter_blocking_section();
+
if (timeout == -1)
continue;