Issue #16288 has been updated by davidw (David Welton).
> --- a/thread.c
> +++ b/thread.c
> @@ -682,7 +682,7 @@ thread_do_start(rb_thread_t *th)
> else {
> args_ptr = RARRAY_CONST_PTR(args);
> }
> -
> + rb_funcallv(NULL, idInspect, 0, 0);
> th->value = rb_vm_invoke_proc(th->ec, proc,
> (int)args_len, args_ptr,
> VM_BLOCK_HANDLER_NONE);
>
I replaced the funcall with
RUBY_VM_CHECK_INTS(GET_EC());
And everything seems to work ok.
I realized that even in 'normal' circumstances, Ruby does not wait for threads to finish; the programmer must request that, so I'm not sure that's actually correct.
With the above patch, I don't get the segfault any more.
I don't have nearly enough familiarity with the internals to know if this is actually the best or most correct way of fixing the problem though.
Thank you
----------------------------------------
Bug #16288: Segmentation fault with finalizers, threads
https://bugs.ruby-lang.org/issues/16288#change-83251
* Author: davidw (David Welton)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v: ruby 2.6.6p116 (2019-10-02 revision 67825) [x86_64-linux]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
Hi,
This is a tricky one and I am still working on narrowing it down, but I will report what I have so far.
I compiled a version of 2_6_6 from github: ruby 2.6.6p116 (2019-10-02 revision 67825) [x86_64-linux]
I have a minimal Rails project that uses Mongoid. It crashes with a segmentation fault when rspec runs. The concurrent ruby gem is in some way involved, and I have been posting there: https://github.com/ruby-concurrency/concurrent-ruby/issues/808
However, I think there is a deeper problem - I would not expect a user level script to cause a segmentation fault.
I have been putting a lot of debugging statements in, and turned on Thread.DEBUG, and have noticed some things. I am not experienced with Ruby's internals, so some of these bits of data might be normal or irrelevant:
* The concurrent-ruby gem uses ObjectSpace.define_finalizer to set a finalizer
* That finalizer creates a new Thread
* However, it appears as if that thread is running after the main thread is already dead, so code that expects to reference the main thread crashes, because it's a NULL reference.
I tried the following test code:
```
class Foo
def initialize
ObjectSpace.define_finalizer(self, proc do
Foo.foo_finalizer
end)
end
def bar
puts 'bar'
end
def Foo.foo_finalizer
puts "foo_finalizer"
t = Thread.new do
puts "Thread reporting for duty"
end
puts "foo_finalizer thread launched"
sleep 5
end
end
f = Foo.new
f.bar
f = nil
```
While trying to develop a simple test case to demonstrate the problem. It triggers rb_raise(rb_eThreadError, "can't alloc thread"); in thread_s_new, because it looks like the main thread has already been marked as 'killed' in this case. When I check the main thread status in thread_s_new with the above code, it reports 'dead'.
When I run my rspec code in the sample Rails project, thread_s_new shows the main thread's status as 'run' even if it should be dead?
I have seen some debugging things that shows some exceptions and thread_join interrupts and so on.
Is it possible that something like this is happening?
Main thread starts doing a cleanup, and gets an exception or something that generates an interrupt, and its KILLED status gets reset to RUNNABLE
Then, in the finalizer, it starts creating a Thread, but at this point the main thread actually does get killed, and when that finalizer thread tries to run it runs into a null reference?
I can provide the Rails sample project if needs be.
Sorry if any of the above isn't clear; I've been staring at the C code for several hours and am a bit cross-eyed!
Thank you for any insights.
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.