Hello,
I’m having trouble embedding Ruby 1.9 inside a pthread because calling
ruby_sysinit() is segfaulting. I created a small example to reproduce
the problem and illustrate my humble goal. (The reason for this weird
way of embedding Ruby is: I need to embed Ruby inside a Verilog HDL
simulator and this is the best way I could accomplish it!).
There are three files in this example:
$ ls
extconf.rb hello.rb main.c
First, we have a simple Ruby script:
$ cat hello.rb
puts “Hello World!”
Second, we have a Makefile generator:
$ cat extconf.rb
require ‘mkmf’
have_library(‘pthread’, ‘pthread_create’)
have_library(‘ruby’, ‘ruby_init’) ||
have_library(‘ruby-static’, ‘ruby_init’)
create_makefile(‘main’)
Finally, we have a C program:
$ cat main.c
#include <stdio.h>
#include <pthread.h>
#include <ruby.h>
RUBY_GLOBAL_SETUP
pthread_t gRubyThread;
pthread_mutex_t gCProgLock;
void* gRubyThread_body(void* dummy)
{
int argc = 0;
char* argv[1];
printf("Ruby thread is calling ruby_sysinit()\n");
ruby_sysinit(&argc, &argv);
{
printf("Ruby thread is calling RUBY_INIT_STACK()\n");
RUBY_INIT_STACK;
printf("Ruby thread is calling ruby_init()\n");
ruby_init();
char* file = "hello.rb"; // the file to run
printf("Ruby interpreter is loading file: %s\n", file);
void* node = rb_load_file(file);
printf("Ruby thread is starting interpreter\n");
ruby_run_node(node);
}
printf("Ruby thread is done, waking up C program...\n");
pthread_mutex_unlock(&gCProgLock);
return NULL;
}
int main(int argc, char** argv)
{
pthread_mutex_init(&gCProgLock, NULL);
pthread_mutex_lock(&gCProgLock);
printf("C program is putting Ruby thread in control...\n");
pthread_create(&gRubyThread, NULL, gRubyThread_body, NULL);
pthread_mutex_lock(&gCProgLock); // C program blocks here
printf("C program got control back from Ruby thread,
exiting…\n");
return 0;
}
This C program is very simple: it creates a new pthread and locks
itself. (At this point, only the pthread in running.) The pthread then
proceeds to embed a Ruby 1.9 interpreter inside itself and have the
interpreter run the “hello.rb” file. Once this is complete, the pthread
unlocks the main C program and dies. Finally, the main C program exits.
Now let’s try running this example.
Here’s the version of Ruby 1.9 I am using (the official release):
$ ruby -v
ruby 1.9.0 (2007-12-25 revision 14709) [i686-linux]
Generate the makefile:
$ ruby extconf.rb
checking for pthread_create() in -lpthread… yes
checking for ruby_init() in -lruby… no
checking for ruby_init() in -lruby-static… yes
creating Makefile
Build the C extension:
$ make
gcc -I. -I/home/sun/app/ruby19/include/ruby-1.9.0/i686-linux
-I/home/sun/app/ruby19/include/ruby-1.9.0 -I. -D_FILE_OFFSET_BITS=64
-fPIC -g -O2 -o main.o -c main.c
main.c: In function ‘gRubyThread_body’:
main.c:16: warning: passing argument 2 of ‘ruby_sysinit’ from
incompatible pointer type
gcc -shared -o main.so main.o -L. -L/home/sun/app/ruby19/lib
-Wl,-R/home/sun/app/ruby19/lib -L. -rdynamic -Wl,-export-dynamic
-lruby-static -lpthread -lpthread -lrt -ldl -lcrypt -lm -lc
Copy and paste the last gcc command (from the output above) and remove
the “-shared” option, and then run the new command:
$ gcc -o main.so main.o -L. -L/home/sun/app/ruby19/lib
-Wl,-R/home/sun/app/ruby19/lib -L. -rdynamic -Wl,-export-dynamic
-lruby-static -lpthread -lpthread -lrt -ldl -lcrypt -lm -lc
Now run the C program:
$ ./main.so
C program is putting Ruby thread in control…
Ruby thread is calling ruby_sysinit()
Segmentation fault (core dumped)
As you can see, ruby_sysinit() core dumped on us. Why?
Thanks for your consideration.