summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2020-11-10 18:21:11 +0900
committerKoichi Sasada <ko1@atdot.net>2020-11-11 15:49:02 +0900
commitdb31ace934e8b900e90853bd875f23195837b398 (patch)
treef9e1e0999b574c0adf974e885420781b2dbd5a15
parent1e8abe5d03ae386af82e2c95ef05170cd9791889 (diff)
Threads in a ractor will be killed with the ractor
If a terminating ractor has child threads, then kill all child threads.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3754
-rw-r--r--bootstraptest/test_ractor.rb34
-rw-r--r--eval_intern.h1
-rw-r--r--ractor.c4
-rw-r--r--thread.c14
4 files changed, 42 insertions, 11 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index 527059d97b..86a033cba8 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -396,6 +396,39 @@ assert_equal '[RuntimeError, "ok", true]', %q{
end
}
+# threads in a ractor will killed
+assert_equal '{:ok=>3}', %q{
+ Ractor.new Ractor.current do |main|
+ q = Queue.new
+ Thread.new do
+ q << true
+ loop{}
+ ensure
+ main << :ok
+ end
+
+ Thread.new do
+ q << true
+ while true
+ end
+ ensure
+ main << :ok
+ end
+
+ Thread.new do
+ q << true
+ sleep 1
+ ensure
+ main << :ok
+ end
+
+ # wait for the start of all threads
+ 3.times{q.pop}
+ end
+
+ 3.times.map{Ractor.receive}.tally
+}
+
# unshareable object are copied
assert_equal 'false', %q{
obj = 'str'.dup
@@ -516,7 +549,6 @@ assert_equal [false, true, false].inspect, %q{
results << check(C.new(false).freeze) # false
}
-
# move example2: String
# touching moved object causes an error
assert_equal 'hello world', %q{
diff --git a/eval_intern.h b/eval_intern.h
index 83d7056234..34489777a2 100644
--- a/eval_intern.h
+++ b/eval_intern.h
@@ -293,7 +293,6 @@ rb_cref_t *rb_vm_cref(void);
rb_cref_t *rb_vm_cref_replace_with_duplicated_cref(void);
VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename);
void rb_vm_set_progname(VALUE filename);
-void rb_thread_terminate_all(void);
VALUE rb_vm_cbase(void);
/* vm_backtrace.c */
diff --git a/ractor.c b/ractor.c
index c30f5ce6c2..350e9c7b3f 100644
--- a/ractor.c
+++ b/ractor.c
@@ -1591,7 +1591,7 @@ rb_ractor_terminate_interrupt_main_thread(rb_ractor_t *r)
}
}
-void rb_thread_terminate_all(void); // thread.c
+void rb_thread_terminate_all(rb_thread_t *th); // thread.c
static void
ractor_terminal_interrupt_all(rb_vm_t *vm)
@@ -1620,7 +1620,7 @@ rb_ractor_terminate_all(void)
ractor_terminal_interrupt_all(vm); // kill all ractors
RB_VM_UNLOCK();
}
- rb_thread_terminate_all(); // kill other threads in main-ractor and wait
+ rb_thread_terminate_all(GET_THREAD()); // kill other threads in main-ractor and wait
RB_VM_LOCK();
{
diff --git a/thread.c b/thread.c
index d0187ae1a3..ad1f4764bb 100644
--- a/thread.c
+++ b/thread.c
@@ -587,16 +587,15 @@ rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th)
}
void
-rb_thread_terminate_all(void)
+rb_thread_terminate_all(rb_thread_t *th)
{
- rb_thread_t *volatile th = GET_THREAD(); /* main thread */
+ rb_ractor_t *cr = th->ractor;
rb_execution_context_t * volatile ec = th->ec;
- rb_ractor_t *r = th->ractor;
volatile int sleeping = 0;
- if (r->threads.main != th) {
+ if (cr->threads.main != th) {
rb_bug("rb_thread_terminate_all: called by child thread (%p, %p)",
- (void *)r->threads.main, (void *)th);
+ (void *)cr->threads.main, (void *)th);
}
/* unlock all locking mutexes */
@@ -606,9 +605,9 @@ rb_thread_terminate_all(void)
if (EC_EXEC_TAG() == TAG_NONE) {
retry:
thread_debug("rb_thread_terminate_all (main thread: %p)\n", (void *)th);
- terminate_all(th->ractor, th);
+ terminate_all(cr, th);
- while (rb_ractor_living_thread_num(th->ractor) > 1) {
+ while (rb_ractor_living_thread_num(cr) > 1) {
rb_hrtime_t rel = RB_HRTIME_PER_SEC;
/*q
* Thread exiting routine in thread_start_func_2 notify
@@ -854,6 +853,7 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start)
}
if (th->invoke_type == thread_invoke_type_ractor_proc) {
+ rb_thread_terminate_all(th);
rb_ractor_teardown(th->ec);
}