Embeded Ruby in a CPP thread crashes
I am creating a embedded Ruby framework which works if I run it normally/once. When I try to run it in a threaded loop the program crashes.
Example which works:
myRubyfile.rb:
def helloworld()
puts "Hello world"
end
Working main.cpp:
#include <ruby.h>
void runRuby()
{
ruby_init();
ruby_init_loadpath();
rb_require("myRubyfile");
rb_funcall(rb_mKernel, rb_intern("helloworld"), 0 , NULL);
ruby_finalize();
}
int main()
{
runRuby();
return 0;
}
The above program executes correctly.
However, I want to run several Ruby scripts in multiple threads the below example runs once and then crashes.
Crashing main.cpp:
#include <ruby.h>
#include <thread>
void runRuby()
{
ruby_init();
ruby_init_loadpath();
rb_require("myRubyfile");
rb_funcall(rb_mKernel, rb_intern("helloworld"), 0 , NULL);
ruby_finalize();
}
int main()
{
for(int i = 0; i < 100; i++) {
std::thread mythread(runRuby);
mythread.join();
}
return 0;
}
I am running this in Windows.
Why is this failing?
It fails because the Ruby VM is not thread safe. You need to use Ruby's Thread class just like in normal Ruby. thread.c
has most of the functions you'll need:
VALUE myThread(VALUE arg)
{
// ...
}
int main()
{
ruby_init();
VALUE threads[100];
for(int i = 0; i < 100; ++i)
threads[i] = rb_thread_create(RUBY_METHOD_FUNC(myThread), Qnil);
for(int i = 0; i < 100; ++i)
rb_funcall(threads[i], rb_intern("join"), 0);
return ruby_cleanup(0);
}
Since Ruby's threads are not truly parallel the only way to really load and run scripts in parallel is to start multiple VMs in different subprocesses.
https://stackoverflow.com/questions/26488029/embeded-ruby-in-a-cpp-thread-crashes