summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorKJ Tsanaktsidis <ktsanaktsidis@zendesk.com>2023-06-01 16:37:18 +0800
committerGitHub <noreply@github.com>2023-06-01 17:37:18 +0900
commitedee9b6a12ac846d7b3de2d704e170bf28178cb3 (patch)
treef0b4af6454d65cc42eb22f58073691bfbd8667e3 /internal
parentd8f333491e4c26df7ca577f40d7708d5aedf764f (diff)
Use a real Ruby mutex in rb_io_close_wait_list (#7884)
Because a thread calling IO#close now blocks in a native condvar wait, it's possible for there to be _no_ threads left to actually handle incoming signals/ubf calls/etc. This manifested as failing tests on Solaris 10 (SPARC), because: * One thread called IO#close, which sent a SIGVTALRM to the other thread to interrupt it, and then waited on the condvar to be notified that the reading thread was done. * One thread was calling IO#read, but it hadn't yet reached the actual call to select(2) when the SIGVTALRM arrived, so it never unblocked itself. This results in a deadlock. The fix is to use a real Ruby mutex for the close lock; that way, the closing thread goes into sigwait-sleep and can keep trying to interrupt the select(2) thread. See the discussion in: https://github.com/ruby/ruby/pull/7865/
Notes
Notes: Merged-By: ioquatix <samuel@codeotaku.com>
Diffstat (limited to 'internal')
-rw-r--r--internal/thread.h7
1 files changed, 3 insertions, 4 deletions
diff --git a/internal/thread.h b/internal/thread.h
index 7a6a860aeb..c41a16c12d 100644
--- a/internal/thread.h
+++ b/internal/thread.h
@@ -11,7 +11,6 @@
#include "ruby/ruby.h" /* for VALUE */
#include "ruby/intern.h" /* for rb_blocking_function_t */
#include "ccan/list/list.h" /* for list in rb_io_close_wait_list */
-#include "ruby/thread_native.h" /* for mutexes in rb_io_close_wait_list */
struct rb_thread_struct; /* in vm_core.h */
@@ -55,9 +54,9 @@ VALUE rb_exec_recursive_outer_mid(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g,
int rb_thread_wait_for_single_fd(int fd, int events, struct timeval * timeout);
struct rb_io_close_wait_list {
- struct ccan_list_head list;
- rb_nativethread_lock_t mu;
- rb_nativethread_cond_t cv;
+ struct ccan_list_head pending_fd_users;
+ VALUE closing_thread;
+ VALUE wakeup_mutex;
};
int rb_notify_fd_close(int fd, struct rb_io_close_wait_list *busy);
void rb_notify_fd_close_wait(struct rb_io_close_wait_list *busy);