From: Suraj Kurapati Date: 2008-03-04T07:50:00+09:00 Subject: embedding Ruby 1.9.0 inside pthread Hello, I am using ruby 1.9.0 (2007-12-25 revision 14709) [i686-linux]. I'm having trouble embedding Ruby inside a pthread because calling ruby_sysinit() is segfaulting. I created a small example to reproduce the problem and illustrate my humble goal. 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 #include #include RUBY_GLOBAL_SETUP pthread_t gRubyThread; pthread_mutex_t gCProgLock; void* gRubyThread_body(void* dummy) { int fake_argc = 0; char* fake_argv[1]; printf("Ruby thread is calling ruby_sysinit()\n"); ruby_sysinit(&fake_argc, &fake_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 is back in control, 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. I should clarify that although the main.c in this example has argc and argv, when I deploy my C extension as a .so file, I do not have any access to the main() method of the C program. For this reason, I did not pass the argc and argv from main() to the body of the gRubyThread (because that is the real-life scenario of this simple example). And since ruby_sysinit() requires an argc and argv, I was forced to fabricate them inside the body of gRubyThread. Now let's try running this example. 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. Then remove the "-shared" option. And 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.