Nobuyoshi Nakada wrote: > At Tue, 4 Mar 2008 14:57:36 +0900, > Suraj N. Kurapati wrote in [ruby-core:15767]: >> [1..2] Thanks for the explanations. >> 3. Is it safe to "compile" the hello.rb file into a NODE in the main >> thread and then execute it inside a child thread? Will there be any >> cross-thread violations by doing this? > > I guess safe. I certainly hope so! :-) > Your example does create new thread outside of ruby, the > interpreter doesn't know about the thread. You should use > rb_thread_create() instead. I tried your suggestion, but it did not work very well for me (see below). Perhaps I wrote a poor implementation? Here is the new C program, revised according to your suggestion: $ cat main.c #include <stdio.h> #include <pthread.h> #include <ruby.h> // aRubyProgram:: program node for the interpreter to run VALUE the_ruby_thread(void* aRubyProgram) { printf("Ruby thread is starting interpreter\n"); ruby_run_node(aRubyProgram); printf("Ruby thread is done...\n"); return Qtrue; } RUBY_GLOBAL_SETUP void the_c_program() { char* file = "hello.rb"; // the file to run int fake_argc = 2; char* fake_args[fake_argc]; fake_args[0] = "ruby"; fake_args[1] = file; char** fake_argv = fake_args; printf("C program is calling ruby_sysinit()\n"); ruby_sysinit(&fake_argc, &fake_argv); printf("C program is calling RUBY_INIT_STACK()\n"); RUBY_INIT_STACK; printf("C program is calling ruby_init()\n"); ruby_init(); printf("C program is calling ruby_init_loadpath()\n"); ruby_init_loadpath(); printf("C program is loading file: %s\n", file); void* rubyProgram = ruby_options(fake_argc, fake_argv); printf("C program is putting Ruby thread in control...\n"); rb_thread_create(the_ruby_thread, rubyProgram); rb_thread_schedule(); printf("C program is back in control, exiting...\n"); } int main(int argc, char** argv) { the_c_program(); return 0; } With hello.rb as: $ cat hello.rb puts "Hello World!" require 'rubygems' puts "rubygems OK!" The result of the C program is: $ ./main.so [BUG] rb_thread_terminate_all: called by child thread (0x8170160, 0x81bea60) ruby 1.9.0 (2007-12-25 revision 14709) [i686-linux] -- control frame ---------- c:0001 p:---- s:0002 b:0002 l:000001 d:000001 TOP --------------------------- -- backtrace of native function call (Use addr2line) -- 0x80f0e0a 0x810ed0c 0x810ed7b 0x80f3a75 0x8060ab2 0x8060b62 0x805a93b 0x80f4a3e 0x80f4ac1 0xb7f5c46b 0xb7e7f6de ------------------------------------------------------- C program is calling ruby_sysinit() C program is calling RUBY_INIT_STACK() C program is calling ruby_init() C program is calling ruby_init_loadpath() C program is loading file: hello.rb C program is putting Ruby thread in control... Ruby thread is starting interpreter However, with hello.rb as: $ cat hello.rb puts "Hello World!" require 'rubygems' puts "rubygems OK!" print 'Ruby is waiting... ' sleep 3 puts 'done!' The result of the C program is: $ ./main.so C program is calling ruby_sysinit() C program is calling RUBY_INIT_STACK() C program is calling ruby_init() C program is calling ruby_init_loadpath() C program is loading file: hello.rb C program is putting Ruby thread in control... Ruby thread is starting interpreter C program is back in control, exiting... Notice that the C program did not wait for the_ruby_thread() to finish. Is there a function in the ruby C API that allows me to wait for a child thread to finish (not rb_thread_join)? I cannot simply join the child thread because in the real-world application of this example, I need to repeatedly transfer control from the main C program to the child thread about 30_000 times. Thanks for your consideration.