aboutsummaryrefslogtreecommitdiffstats
path: root/thread.c
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2022-10-07 21:48:38 +1300
committerGitHub <noreply@github.com>2022-10-07 21:48:38 +1300
commite4f91bbdbaa6ab3125f24967414ac5300bb244f5 (patch)
tree575f8febdd50601522c5e5ec72f3436139304537 /thread.c
parente76217a7f3957c9cea52832c2f4237130411f7dd (diff)
downloadruby-e4f91bbdbaa6ab3125f24967414ac5300bb244f5.tar.gz
Add IO#timeout attribute and use it for blocking IO operations. (#5653)
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/thread.c b/thread.c
index 1364d73be2..e1b194861a 100644
--- a/thread.c
+++ b/thread.c
@@ -1675,6 +1675,12 @@ rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
.th = rb_ec_thread_ptr(ec)
};
+ // `errno` is only valid when there is an actual error - but we can't
+ // extract that from the return value of `func` alone, so we clear any
+ // prior `errno` value here so that we can later check if it was set by
+ // `func` or not (as opposed to some previously set value).
+ errno = 0;
+
RB_VM_LOCK_ENTER();
{
ccan_list_add(&rb_ec_vm_ptr(ec)->waiting_fds, &waiting_fd.wfd_node);
@@ -1706,6 +1712,11 @@ rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
/* TODO: check func() */
RUBY_VM_CHECK_INTS_BLOCKING(ec);
+ // If the error was a timeout, we raise a specific exception for that:
+ if (saved_errno == ETIMEDOUT) {
+ rb_raise(rb_eIOTimeoutError, "Blocking operation timed out!");
+ }
+
errno = saved_errno;
return val;