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

ruby-changes:69873

From: nagachika <ko1@a...>
Date: Tue, 23 Nov 2021 15:12:11 +0900 (JST)
Subject: [ruby-changes:69873] 949af69408 (ruby_3_0): merge revision(s) 5680c38c75aeb5cbd219aafa8eb48c315f287d97,f5d20411386ff2552ff27661387ddc4bae1ebc30: [Backport #17573]

https://git.ruby-lang.org/ruby.git/commit/?id=949af69408

From 949af69408e44b69cc7437b58e8edbe3cd77c966 Mon Sep 17 00:00:00 2001
From: nagachika <nagachika@r...>
Date: Tue, 23 Nov 2021 14:26:20 +0900
Subject: merge revision(s)
 5680c38c75aeb5cbd219aafa8eb48c315f287d97,f5d20411386ff2552ff27661387ddc4bae1ebc30:
 [Backport #17573]

	Use valid `ec` for postponed job.

	Postponed job can be registered from non-Ruby thread, which means
	`ec` in TLS can be NULL. In this case, use main thread's `ec` instead.

	See https://github.com/ruby/ruby/pull/4108
	and https://github.com/ruby/ruby/pull/4336
	---
	 vm_trace.c | 16 ++++++++++++----
	 1 file changed, 12 insertions(+), 4 deletions(-)

	Avoid assert failure when NULL EC is expected

	After 5680c38c75aeb5cbd219aafa8eb48c315f287d97, postponed job APIs now
	expect to be called on native threads not managed by Ruby and handles
	getting a NULL execution context. However, in debug builds the change
	runs into an assertion failure with GET_EC() which asserts that EC is
	non-NULL. Avoid the assertion failure by passing `false` for `expect_ec`
	instead as the intention is to handle when there is no EC.

	Add a test from John Crepezzi and John Hawthorn to exercise this
	situation.

	See GH-4108
	See GH-5094

	[Bug #17573]

	Co-authored-by: John Hawthorn <john@h...>
	Co-authored-by: John Crepezzi <john.crepezzi@g...>
	---
	 ext/-test-/postponed_job/postponed_job.c       | 31 ++++++++++++++++++++++++++
	 test/-ext-/postponed_job/test_postponed_job.rb |  7 ++++++
	 vm_trace.c                                     |  2 +-
	 3 files changed, 39 insertions(+), 1 deletion(-)
---
 ext/-test-/postponed_job/postponed_job.c       | 31 ++++++++++++++++++++++++++
 test/-ext-/postponed_job/test_postponed_job.rb |  7 ++++++
 version.h                                      |  2 +-
 vm_trace.c                                     | 16 +++++++++----
 4 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/ext/-test-/postponed_job/postponed_job.c b/ext/-test-/postponed_job/postponed_job.c
index d8684d475a4..fa57bef6f5a 100644
--- a/ext/-test-/postponed_job/postponed_job.c
+++ b/ext/-test-/postponed_job/postponed_job.c
@@ -58,6 +58,34 @@ pjob_call_direct(VALUE self, VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/-test-/postponed_job/postponed_job.c#L58
     return self;
 }
 
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+
+static void *
+pjob_register_in_c_thread_i(void *obj)
+{
+    rb_postponed_job_register_one(0, pjob_one_callback, (void *)obj);
+    rb_postponed_job_register_one(0, pjob_one_callback, (void *)obj);
+    rb_postponed_job_register_one(0, pjob_one_callback, (void *)obj);
+    return NULL;
+}
+
+static VALUE
+pjob_register_in_c_thread(VALUE self, VALUE obj)
+{
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, pjob_register_in_c_thread_i, (void *)obj)) {
+        return Qfalse;
+    }
+
+    if (pthread_join(thread, NULL)) {
+        return Qfalse;
+    }
+
+    return Qtrue;
+}
+#endif
+
 void
 Init_postponed_job(VALUE self)
 {
@@ -65,5 +93,8 @@ Init_postponed_job(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/-test-/postponed_job/postponed_job.c#L93
     rb_define_module_function(mBug, "postponed_job_register", pjob_register, 1);
     rb_define_module_function(mBug, "postponed_job_register_one", pjob_register_one, 1);
     rb_define_module_function(mBug, "postponed_job_call_direct", pjob_call_direct, 1);
+#ifdef HAVE_PTHREAD_H
+    rb_define_module_function(mBug, "postponed_job_register_in_c_thread", pjob_register_in_c_thread, 1);
+#endif
 }
 
diff --git a/test/-ext-/postponed_job/test_postponed_job.rb b/test/-ext-/postponed_job/test_postponed_job.rb
index 7dc28776d0c..fee0172d114 100644
--- a/test/-ext-/postponed_job/test_postponed_job.rb
+++ b/test/-ext-/postponed_job/test_postponed_job.rb
@@ -25,4 +25,11 @@ class TestPostponed_job < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/postponed_job/test_postponed_job.rb#L25
     Bug.postponed_job_register_one(ary = [])
     assert_equal [1], ary
   end
+
+  if Bug.respond_to?(:postponed_job_register_in_c_thread)
+    def test_register_in_c_thread
+      assert Bug.postponed_job_register_in_c_thread(ary = [])
+      assert_equal [1], ary
+    end
+  end
 end
diff --git a/version.h b/version.h
index 8a0f53d9b9f..155977aa363 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 152
+#define RUBY_PATCHLEVEL 153
 
 #define RUBY_RELEASE_YEAR 2021
 #define RUBY_RELEASE_MONTH 11
diff --git a/vm_trace.c b/vm_trace.c
index b16ec77e5af..bb4fdefd7c1 100644
--- a/vm_trace.c
+++ b/vm_trace.c
@@ -1592,6 +1592,14 @@ postponed_job_register(rb_execution_context_t *ec, rb_vm_t *vm, https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L1592
     return PJRR_SUCCESS;
 }
 
+static rb_execution_context_t *
+get_valid_ec(rb_vm_t *vm)
+{
+    rb_execution_context_t *ec = rb_current_execution_context();
+    if (ec == NULL) ec = rb_vm_main_ractor_ec(vm);
+    return ec;
+}
+
 /*
  * return 0 if job buffer is full
  * Async-signal-safe
@@ -1599,8 +1607,8 @@ postponed_job_register(rb_execution_context_t *ec, rb_vm_t *vm, https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L1607
 int
 rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void *data)
 {
-    rb_execution_context_t *ec = GET_EC();
-    rb_vm_t *vm = rb_ec_vm_ptr(ec);
+    rb_vm_t *vm = GET_VM();
+    rb_execution_context_t *ec = get_valid_ec(vm);
 
   begin:
     switch (postponed_job_register(ec, vm, flags, func, data, MAX_POSTPONED_JOB, vm->postponed_job_index)) {
@@ -1618,8 +1626,8 @@ rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L1626
 int
 rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data)
 {
-    rb_execution_context_t *ec = GET_EC();
-    rb_vm_t *vm = rb_ec_vm_ptr(ec);
+    rb_vm_t *vm = GET_VM();
+    rb_execution_context_t *ec = get_valid_ec(vm);
     rb_postponed_job_t *pjob;
     rb_atomic_t i, index;
 
-- 
cgit v1.2.1


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

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