Bug #4992
closedfinalizer中のThread.newでSEGV
Description
以下のようなコードを実行するとSEGVします.
$ ruby -e'ObjectSpace.define_finalizer(""){Thread.new{}}'
$ ruby -e'ObjectSpace.define_finalizer(""){Thread.new{}}'
SEGV received in SEGV handler
$ ruby -e'ObjectSpace.define_finalizer(""){2.times{Thread.new{}}}'
SEGV received in SEGV handler
$ ruby -e'ObjectSpace.define_finalizer(""){2.times{Thread.new{}}}'
SEGV received in SEGV handler
2.timesをつけるとほぼ確実,つけないと2回に1回くらいの割合で再現します.
Updated by sorah (Sorah Fukumori) over 13 years ago
Oops, I sent this issue into ruby-core.
I wrote this issue again in English:
-- Thread.new in finalizer raises SEGV
The following code raises SEGV sometimes:
$ ruby -e'ObjectSpace.define_finalizer(""){Thread.new{}}'
$ ruby -e'ObjectSpace.define_finalizer(""){Thread.new{}}'
SEGV received in SEGV handler
But this code raises SEGV authenticity:
$ ruby -e'ObjectSpace.define_finalizer(""){2.times{Thread.new{}}}'
SEGV received in SEGV handler
$ ruby -e'ObjectSpace.define_finalizer(""){2.times{Thread.new{}}}'
SEGV received in SEGV handler
Updated by kosaki (Motohiro KOSAKI) over 13 years ago
- ruby -v changed from ruby 1.9.3dev (2011-07-05 trunk 32413) [x86_64-darwin10.8.0] to -
-- Thread.new in finalizer raises SEGV
The following code raises SEGV sometimes:
$ ruby -e'ObjectSpace.define_finalizer(""){Thread.new{}}'
$ ruby -e'ObjectSpace.define_finalizer(""){Thread.new{}}'
SEGV received in SEGV handler
I think Thread.new in finalizer should raise argument error.
IOW, we shouldn't allow to create new thread in finalizer.
It's disaster. just my 2 cent.
Updated by ko1 (Koichi Sasada) over 13 years ago
(2011/07/08 10:24), KOSAKI Motohiro wrote:
IOW, we shouldn't allow to create new thread in finalizer.
It's disaster. just my 2 cent.
Why that?
--
// SASADA Koichi at atdot dot net
Updated by kosaki (Motohiro KOSAKI) over 13 years ago
2011/7/8 SASADA Koichi ko1@atdot.net:
(2011/07/08 10:24), KOSAKI Motohiro wrote:
IOW, we shouldn't allow to create new thread in finalizer.
It's disaster. just my 2 cent.Why that?
After ruby_finalize_1(), main thread start to destruct various core data
structure (eg GVL), therefore subthread have no guarantee to don't get
SEGV.
Updated by kosaki (Motohiro KOSAKI) over 13 years ago
- Status changed from Open to Assigned
- Assignee set to kosaki (Motohiro KOSAKI)
- Target version set to 1.9.3
Updated by kosaki (Motohiro KOSAKI) over 13 years ago
- Assignee changed from kosaki (Motohiro KOSAKI) to ko1 (Koichi Sasada)
How's this?
Index: vm_core.h
===================================================================
--- vm_core.h (revision 32446)
+++ vm_core.h (working copy)
@@ -285,6 +285,7 @@
VALUE thgroup_default;
int running;
+ int inhibit_thread_creation;
int thread_abort_on_exception;
unsigned long trace_flag;
volatile int sleeper;
Index: thread.c
===================================================================
--- thread.c (revision 32447)
+++ thread.c (working copy)
@@ -367,6 +367,7 @@
thread_debug("rb_thread_terminate_all (main thread: %p)\n", (void *)th);
st_foreach(vm->living_threads, terminate_i, (st_data_t)th);
+ vm->inhibit_thread_creation = 1;
while (!rb_thread_alone()) {
PUSH_TAG();
@@ -583,6 +584,10 @@
{
rb_thread_t *th;
VALUE thread = rb_thread_alloc(klass);
+
+ if (GET_VM()->inhibit_thread_creation)
+ rb_raise(rb_eThreadError, "can't alloc thread");
+
rb_obj_call_init(thread, argc, argv);
GetThreadPtr(thread, th);
if (!th->first_args) {
Updated by ko1 (Koichi Sasada) over 13 years ago
Motohiro KOSAKI wrote:
How's this?
Thank you. On 1.9.3, it is Okay. Could you commit it?
Updated by kosaki (Motohiro KOSAKI) over 13 years ago
- Status changed from Assigned to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r32492.
Shota, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
-
vm_core.h (typedef struct rb_vm_struct): create a new
'inhibit_thread_createion' field. -
thread.c (rb_thread_terminate_all): set inhibit_thread_creation.
-
thread.c (thread_s_new): don't permit to create new thread
if the VM is under destruction. Otherwise evil finalizer code
can make SEGV. [Bug #4992][ruby-core:37858] -
bootstraptest/test_objectspace.rb: new test for this fix.
Updated by nobu (Nobuyoshi Nakada) almost 2 years ago
Thread.new
is prohibited but not Thread.start
.
$ ruby -v --disable=gems -d -e 'class E<StandardError;def detailed_message(...) Thread.start{"<#{super}>"}.value; end; end' -e 'raise E'
ruby 3.2.0dev (2022-11-13T14:54:43Z master 2f7d2662dd) [x86_64-darwin21]
Exception `E' at -e:2 - E
-e:2:in `<main>': <E (E)>
bash: exit 1