From c7e0312c65d73bf10e05aa012ffe55bf204c1de2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 6 Oct 2025 07:40:07 +0900 Subject: [PATCH] mruby-task: fix sleep to work correctly with sigalrm timer The sleep implementation now properly handles signal interruptions from the sigalrm timer by using nanosleep with retry loop instead of usleep. This commit also makes sleep override mruby-sleep's implementation when both gems are loaded, providing task-aware sleep behavior. Changes: - replace usleep with nanosleep for signal-safe blocking sleep - add retry loop to handle eintr interruptions - use mrb_define_private_method_id for both sleep and sleep_ms - add time.h and presym.h headers Co-authored-by: Claude --- mrbgems/mruby-task/src/task.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/mrbgems/mruby-task/src/task.c b/mrbgems/mruby-task/src/task.c index 2909d41ce..a5e6baefe 100644 --- a/mrbgems/mruby-task/src/task.c +++ b/mrbgems/mruby-task/src/task.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #ifdef _WIN32 #include #else +#include #include #endif #include "../include/task.h" @@ -357,9 +359,15 @@ sleep_ms_impl(mrb_state *mrb, mrb_int ms) mrb_task *t = q_ready_; /* Current running task */ if (!t) { - /* Not in task context - use blocking sleep */ + /* Not in task context - use blocking sleep with retry on interruption */ #ifdef __unix__ - usleep((useconds_t)(ms * 1000)); + struct timespec req, rem; + req.tv_sec = ms / 1000; + req.tv_nsec = (ms % 1000) * 1000000; + /* nanosleep automatically retries on EINTR with SA_RESTART */ + while (nanosleep(&req, &rem) == -1) { + req = rem; /* Continue with remaining time if interrupted */ + } #elif defined(_WIN32) Sleep((DWORD)ms); #endif @@ -994,8 +1002,11 @@ mrb_mruby_task_gem_init(mrb_state *mrb) mrb_define_method(mrb, task_class, "terminate", mrb_task_terminate, MRB_ARGS_NONE()); mrb_define_method(mrb, task_class, "join", mrb_task_join, MRB_ARGS_NONE()); - /* Kernel methods */ - mrb_define_method(mrb, mrb->kernel_module, "sleep", mrb_f_sleep, MRB_ARGS_OPT(1)); + /* Kernel methods + * Note: sleep overrides mruby-sleep's implementation to be task-aware + * (cooperative sleep within tasks, blocking sleep otherwise) + */ + mrb_define_private_method_id(mrb, mrb->kernel_module, MRB_SYM(sleep), mrb_f_sleep, MRB_ARGS_OPT(1)); mrb_define_method(mrb, mrb->kernel_module, "sleep_ms", mrb_f_sleep_ms, MRB_ARGS_REQ(1)); }