mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
partially merge revision(s) 5f69a7f604
: [Backport #17666]
Co-authored-by: Samuel Williams <@ioquatix>
2cee515f02
This commit is contained in:
parent
dc7ad0287e
commit
95dc88c888
6 changed files with 55 additions and 4 deletions
5
cont.c
5
cont.c
|
@ -1155,6 +1155,11 @@ VALUE rb_fiberptr_self(struct rb_fiber_struct *fiber)
|
|||
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)
|
||||
|
|
|
@ -21,5 +21,6 @@ void ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(VALUE), VALUE (
|
|||
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 */
|
||||
|
|
45
test/fiber/test_thread.rb
Normal file
45
test/fiber/test_thread.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
# 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
|
2
thread.c
2
thread.c
|
@ -544,7 +544,7 @@ rb_threadptr_join_list_wakeup(rb_thread_t *thread)
|
|||
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);
|
||||
|
|
|
@ -32,7 +32,7 @@ sync_wakeup(struct list_head *head, long max)
|
|||
|
||||
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)
|
|||
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 {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# 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
|
||||
|
|
Loading…
Reference in a new issue