Skip to content

luv fails to handle signals promptly #400

Closed
@talex5

Description

@talex5

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;
 

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions