Project

General

Profile

Actions

Bug #4992

closed

finalizer中のThread.newでSEGV

Added by sorah (Sorah Fukumori) over 13 years ago. Updated almost 2 years ago.

Status:
Closed
Target version:
ruby -v:
-
Backport:
[ruby-core:37858]

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 :

(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?

Actions #8

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
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0