Bug #4992

finalizer中のThread.newでSEGV

Added by Shota Fukumori almost 3 years ago. Updated almost 3 years ago.

[ruby-core:37858]
Status:Closed
Priority:Normal
Assignee:Koichi Sasada
Category:core
Target version:1.9.3
ruby -v:- Backport:

Description

以下のようなコードを実行するとSEGVします.

$ ruby -e'ObjectSpace.definefinalizer(""){Thread.new{}}'

$ ruby -e'ObjectSpace.define
finalizer(""){Thread.new{}}'
SEGV received in SEGV handler
$ ruby -e'ObjectSpace.definefinalizer(""){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回くらいの割合で再現します.

Associated revisions

Revision 32492
Added by Motohiro KOSAKI almost 3 years ago

  • vmcore.h (typedef struct rbvmstruct): create a new 'inhibitthread_createion' field.
  • thread.c (rbthreadterminateall): set inhibitthread_creation.
  • thread.c (threadsnew): don't permit to create new thread
    if the VM is under destruction. Otherwise evil finalizer code
    can make SEGV. [Bug #4992]

  • bootstraptest/test_objectspace.rb: new test for this fix.

History

#1 Updated by Shota Fukumori almost 3 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.definefinalizer(""){Thread.new{}}'

$ ruby -e'ObjectSpace.define
finalizer(""){Thread.new{}}'
SEGV received in SEGV handler

But this code raises SEGV authenticity:

$ ruby -e'ObjectSpace.definefinalizer(""){2.times{Thread.new{}}}'
SEGV received in SEGV handler
$ ruby -e'ObjectSpace.define
finalizer(""){2.times{Thread.new{}}}'
SEGV received in SEGV handler

#2 Updated by Motohiro KOSAKI almost 3 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.definefinalizer(""){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.

#3 Updated by Koichi Sasada almost 3 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

#4 Updated by Motohiro KOSAKI almost 3 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 rubyfinalize1(), main thread start to destruct various core data
structure (eg GVL), therefore subthread have no guarantee to don't get
SEGV.

#5 Updated by Motohiro KOSAKI almost 3 years ago

  • Status changed from Open to Assigned
  • Assignee set to Motohiro KOSAKI
  • Target version set to 1.9.3

#6 Updated by Motohiro KOSAKI almost 3 years ago

  • Assignee changed from Motohiro KOSAKI to Koichi Sasada

How's this?

Index: vm_core.h

--- vmcore.h (revision 32446)
+++ vm
core.h (working copy)
@@ -285,6 +285,7 @@
VALUE thgroup_default;

 int running;
  • int inhibitthreadcreation;
    int threadabortonexception;
    unsigned long trace
    flag;
    volatile int sleeper;

    Index: thread.c

    --- thread.c (revision 32447)
    +++ thread.c (working copy)
    @@ -367,6 +367,7 @@

    threaddebug("rbthreadterminateall (main thread: %p)\n", (void *)th);
    stforeach(vm->livingthreads, terminatei, (stdata_t)th);

  • vm->inhibitthreadcreation = 1;

    while (!rbthreadalone()) {
    PUSHTAG();
    @@ -583,6 +584,10 @@
    {
    rb
    threadt *th;
    VALUE thread = rb
    thread_alloc(klass);
    +

  • if (GETVM()->inhibitthread_creation)

  • rbraise(rbeThreadError, "can't alloc thread");
    +
    rbobjcallinit(thread, argc, argv);
    GetThreadPtr(thread, th);
    if (!th->first
    args) {

#7 Updated by Koichi Sasada almost 3 years ago

Motohiro KOSAKI wrote:

How's this?

Thank you. On 1.9.3, it is Okay. Could you commit it?

#8 Updated by Motohiro KOSAKI almost 3 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.


  • vmcore.h (typedef struct rbvmstruct): create a new 'inhibitthread_createion' field.
  • thread.c (rbthreadterminateall): set inhibitthread_creation.
  • thread.c (threadsnew): don't permit to create new thread
    if the VM is under destruction. Otherwise evil finalizer code
    can make SEGV. [Bug #4992]

  • bootstraptest/test_objectspace.rb: new test for this fix.

Also available in: Atom PDF