[前][次][番号順一覧][スレッド一覧]

ruby-changes:66882

From: nagachika <ko1@a...>
Date: Sun, 25 Jul 2021 14:11:29 +0900 (JST)
Subject: [ruby-changes:66882] 95dc88c888 (ruby_3_0): partially merge revision(s) 5f69a7f60467fa58c2f998daffab43e118bff36c: [Backport #17666]

https://git.ruby-lang.org/ruby.git/commit/?id=95dc88c888

From 95dc88c88869541dd0eccafd14924d78c8d7f427 Mon Sep 17 00:00:00 2001
From: nagachika <nagachika@r...>
Date: Sun, 25 Jul 2021 13:38:05 +0900
Subject: partially merge revision(s) 5f69a7f60467fa58c2f998daffab43e118bff36c:
 [Backport #17666]

Co-authored-by: Samuel Williams <@ioquatix>
https://github.com/nagachika/ruby/pull/1/commits/2cee515f024f3295945f312cb6b052f972f9c93d
---
 cont.c                    |  5 +++++
 internal/cont.h           |  1 +
 test/fiber/test_thread.rb | 45 +++++++++++++++++++++++++++++++++++++++++++++
 thread.c                  |  2 +-
 thread_sync.c             |  4 ++--
 version.h                 |  2 +-
 6 files changed, 55 insertions(+), 4 deletions(-)
 create mode 100644 test/fiber/test_thread.rb

diff --git a/cont.c b/cont.c
index a8250c3..aad7612 100644
--- a/cont.c
+++ b/cont.c
@@ -1155,6 +1155,11 @@ VALUE rb_fiberptr_self(struct rb_fiber_struct *fiber) https://github.com/ruby/ruby/blob/trunk/cont.c#L1155
     return fiber->cont.self;
 }
 
+unsigned int rb_fiberptr_blocking(struct rb_fiber_struct *fiber)
+{
+    return fiber->blocking;
+}
+
 // This is used for root_fiber because other fibers call cont_init_mjit_cont through cont_new.
 void
 rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber)
diff --git a/internal/cont.h b/internal/cont.h
index a365cbe..9e49dd3 100644
--- a/internal/cont.h
+++ b/internal/cont.h
@@ -21,5 +21,6 @@ void ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(VALUE), VALUE ( https://github.com/ruby/ruby/blob/trunk/internal/cont.h#L21
 void rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber);
 
 VALUE rb_fiberptr_self(struct rb_fiber_struct *fiber);
+unsigned int rb_fiberptr_blocking(struct rb_fiber_struct *fiber);
 
 #endif /* INTERNAL_CONT_H */
diff --git a/test/fiber/test_thread.rb b/test/fiber/test_thread.rb
new file mode 100644
index 0000000..5fc80f0
--- /dev/null
+++ b/test/fiber/test_thread.rb
@@ -0,0 +1,45 @@ https://github.com/ruby/ruby/blob/trunk/test/fiber/test_thread.rb#L1
+# frozen_string_literal: true
+require "test/unit"
+require_relative 'scheduler'
+
+class TestFiberThread < Test::Unit::TestCase
+  def test_thread_join
+    thread = Thread.new do
+      scheduler = Scheduler.new
+      Fiber.set_scheduler scheduler
+
+      result = nil
+      Fiber.schedule do
+        result = Thread.new{:done}.value
+      end
+
+      scheduler.run
+      result
+    end
+
+    assert_equal :done, thread.value
+  end
+
+  def test_thread_join_blocking
+    thread = Thread.new do
+      scheduler = Scheduler.new
+      Fiber.set_scheduler scheduler
+
+      result = nil
+      Fiber.schedule do
+        Fiber.new(blocking: true) do
+          # This can deadlock if the blocking state is not taken into account:
+          Thread.new do
+            sleep(0)
+            result = :done
+          end.join
+        end.resume
+      end
+
+      scheduler.run
+      result
+    end
+
+    assert_equal :done, thread.value
+  end
+end
diff --git a/thread.c b/thread.c
index 2ee8789..ec7a9b7 100644
--- a/thread.c
+++ b/thread.c
@@ -544,7 +544,7 @@ rb_threadptr_join_list_wakeup(rb_thread_t *thread) https://github.com/ruby/ruby/blob/trunk/thread.c#L544
     while (join_list) {
         rb_thread_t *target_thread = join_list->thread;
 
-        if (target_thread->scheduler != Qnil) {
+        if (target_thread->scheduler != Qnil && rb_fiberptr_blocking(join_list->fiber) == 0) {
             rb_scheduler_unblock(target_thread->scheduler, target_thread->self, rb_fiberptr_self(join_list->fiber));
         } else {
             rb_threadptr_interrupt(target_thread);
diff --git a/thread_sync.c b/thread_sync.c
index 11d77e8..26d5e6b 100644
--- a/thread_sync.c
+++ b/thread_sync.c
@@ -32,7 +32,7 @@ sync_wakeup(struct list_head *head, long max) https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L32
 
         if (cur->th->status != THREAD_KILLED) {
 
-            if (cur->th->scheduler != Qnil) {
+            if (cur->th->scheduler != Qnil && rb_fiberptr_blocking(cur->fiber) == 0) {
                 rb_scheduler_unblock(cur->th->scheduler, cur->self, rb_fiberptr_self(cur->fiber));
             } else {
                 rb_threadptr_interrupt(cur->th);
@@ -437,7 +437,7 @@ rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th, rb_fiber_t *fiber) https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L437
         list_for_each_safe(&mutex->waitq, cur, next, node) {
             list_del_init(&cur->node);
 
-            if (cur->th->scheduler != Qnil) {
+            if (cur->th->scheduler != Qnil && rb_fiberptr_blocking(cur->fiber) == 0) {
                 rb_scheduler_unblock(cur->th->scheduler, cur->self, rb_fiberptr_self(cur->fiber));
                 goto found;
             } else {
diff --git a/version.h b/version.h
index 44776a9..72cf6b2 100644
--- a/version.h
+++ b/version.h
@@ -12,7 +12,7 @@ https://github.com/ruby/ruby/blob/trunk/version.h#L12
 # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
 #define RUBY_VERSION_TEENY 3
 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 113
+#define RUBY_PATCHLEVEL 114
 
 #define RUBY_RELEASE_YEAR 2021
 #define RUBY_RELEASE_MONTH 7
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]