From 5b6009870dff883a8e71a05e60f175cea1d00d55 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Fri, 13 Sep 2024 17:40:30 +1000 Subject: Ensure fiber scheduler is woken up when close interrupts read If one thread is reading and another closes that socket, the close blocks waiting for the read to abort cleanly. This ensures that Ruby is totally done with the file descriptor _BEFORE_ we tell the OS to close and potentially re-use it. When the read is correctly terminated, the close should be unblocked. That currently works if closing is happening on a thread, but if it's happening on a fiber with a fiber scheduler, it does NOT work. This patch ensures that if the close happened in a fiber scheduled thread, that the scheduler is notified that the fiber is unblocked. [Bug #20723] --- thread.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'thread.c') diff --git a/thread.c b/thread.c index abd91e1e2e..bcafbaacfa 100644 --- a/thread.c +++ b/thread.c @@ -1698,7 +1698,12 @@ thread_io_wake_pending_closer(struct waiting_fd *wfd) RB_VM_LOCK_LEAVE(); if (has_waiter) { - rb_thread_wakeup(wfd->busy->closing_thread); + rb_thread_t *th = rb_thread_ptr(wfd->busy->closing_thread); + if (th->scheduler != Qnil) { + rb_fiber_scheduler_unblock(th->scheduler, wfd->busy->closing_thread, wfd->busy->closing_fiber); + } else { + rb_thread_wakeup(wfd->busy->closing_thread); + } rb_mutex_unlock(wfd->busy->wakeup_mutex); } } @@ -2609,6 +2614,7 @@ rb_notify_fd_close(int fd, struct rb_io_close_wait_list *busy) has_any = !ccan_list_empty(&busy->pending_fd_users); busy->closing_thread = rb_thread_current(); + busy->closing_fiber = rb_fiber_current(); wakeup_mutex = Qnil; if (has_any) { wakeup_mutex = rb_mutex_new(); -- cgit v1.2.3