From: b g Date: 2004-05-25T05:18:35+09:00 Subject: Re: [PATCH] fixed SIG_SEGV in check_stack() in eval.c OK, here comes the C init and calling code. I end up doing about 23 million Ruby calls after initialization (which is done only once). The idea here is that we wish to provide a scripting language inside our app, without having to build one ourselves. (We've maintained internal scripting languages in the past, and it is wasteful of time given the existence of language such as Ruby). So we intend to load application variables into Ruby variables, call Ruby, and transfer back results. Like I said, the number of Ruby calls will reach into the several millions. Since our application depends upon being extremely efficient (it's an EDA app that deals with very large data sets), we need an efficient script-embedding API. This entire exercise is to determine whether Ruby will be "fast enough." Here's the calling code then. Keep in mind that the function Ruby__simulated_compare__test() will be called many times. It does setup and init stuff only once (including first rb_funcall()). Then it basically loads data and calls rb_funcall() upon each subsequent invocation. #include "ruby.h" // These C-side vars get bound to Ruby vars: static VALUE C_l_lay; static VALUE C_l_src; static VALUE C_l_err; static VALUE C_w_lay; static VALUE C_w_src; static VALUE C_w_err; static VALUE C_as_lay; static VALUE C_as_src; static VALUE C_as_err; static VALUE C_ad_lay; static VALUE C_ad_src; static VALUE C_ad_err; static VALUE C_ps_lay; static VALUE C_ps_src; static VALUE C_ps_err; static VALUE C_pd_lay; static VALUE C_pd_src; static VALUE C_pd_err; static bool bRubyIsInit=false; // init Ruby only once, call many times static bool bTracePropertyError=false; /* # The following script is implemented in one line in the psScript_rb string below: # (had troubles getting rb_load_file() to work) # def bg_compare loc_err=($l_lay-$l_src).abs/$l_src if loc_err>0.0001 then; $l_err=loc_err; end loc_err=($w_lay-$w_src).abs/$w_src if loc_err>0.0001 then; $w_err=loc_err; end loc_err=($as_lay-$as_src).abs/$as_src if loc_err>0.0001 then; $as_err=loc_err; end loc_err=($ad_lay-$ad_src).abs/$ad_src if loc_err>0.0001 then; $ad_err=loc_err; end loc_err=($ps_lay-$ps_src).abs/$ps_src if loc_err>0.0001 then; $ps_err=loc_err; end loc_err=($pd_lay-$pd_src).abs/$pd_src if loc_err>0.0001 then; $pd_err=loc_err; end end */ static char psScript_rb[] = "def bg_compare; \ loc_err=($l_lay-$l_src).abs/$l_src; \ if loc_err>0.0001 then; $l_err=loc_err; end; \ loc_err=($w_lay-$w_src).abs/$w_src; \ if loc_err>0.0001 then; $w_err=loc_err; end; \ loc_err=($as_lay-$as_src).abs/$as_src; \ if loc_err>0.0001 then; $as_err=loc_err; end; \ loc_err=($ad_lay-$ad_src).abs/$ad_src; \ if loc_err>0.0001 then; $ad_err=loc_err; end; \ loc_err=($ps_lay-$ps_src).abs/$ps_src; \ if loc_err>0.0001 then; $ps_err=loc_err; end; \ loc_err=($pd_lay-$pd_src).abs/$pd_src; \ if loc_err>0.0001 then; $pd_err=loc_err; end;\ end"; static ID bg_compare__ID; // lookup ID from name only once inline void Ruby__simulated_compare__test() { if ( !bRubyIsInit ) { // basic init stuff ruby_init(); ruby_script("inside_application"); // simply sets $0 to simulated "self name" C_l_lay=rb_float_new(0.0); rb_define_variable("$l_lay",&C_l_lay); C_l_src=rb_float_new(0.0); rb_define_variable("$l_src",&C_l_src); C_l_err=rb_float_new(0.0); rb_define_variable("$l_err",&C_l_err); C_w_lay=rb_float_new(0.0); rb_define_variable("$w_lay",&C_w_lay); C_w_src=rb_float_new(0.0); rb_define_variable("$w_src",&C_w_src); C_w_err=rb_float_new(0.0); rb_define_variable("$w_err",&C_w_err); C_as_lay=rb_float_new(0.0); rb_define_variable("$as_lay",&C_as_lay); C_as_src=rb_float_new(0.0); rb_define_variable("$as_src",&C_as_src); C_as_err=rb_float_new(0.0); rb_define_variable("$as_err",&C_as_err); C_ad_lay=rb_float_new(0.0); rb_define_variable("$ad_lay",&C_ad_lay); C_ad_src=rb_float_new(0.0); rb_define_variable("$ad_src",&C_ad_src); C_ad_err=rb_float_new(0.0); rb_define_variable("$ad_err",&C_ad_err); C_ps_lay=rb_float_new(0.0); rb_define_variable("$ps_lay",&C_ps_lay); C_ps_src=rb_float_new(0.0); rb_define_variable("$ps_src",&C_ps_src); C_ps_err=rb_float_new(0.0); rb_define_variable("$ps_err",&C_ps_err); C_pd_lay=rb_float_new(0.0); rb_define_variable("$pd_lay",&C_pd_lay); C_pd_src=rb_float_new(0.0); rb_define_variable("$pd_src",&C_pd_src); C_pd_err=rb_float_new(0.0); rb_define_variable("$pd_err",&C_pd_err); printf("About to give this script to Ruby: '%s'\n",psScript_rb); fflush(stdout); rb_eval_string(psScript_rb); // hopefully this compiles to byte code... rb_eval_string("x=Object.methods.sort; puts x"); // we should see 'bg_compare' listed // Do the method name (to ID) lookup once. Use on subsequent // rb_funcall()s bg_compare__ID = rb_intern ( "bg_compare" ); // Call once to test VALUE dontcare = rb_funcall ( rb_cObject, bg_compare__ID, 0/*argc*/ /*, ... (none) */ ); rb_eval_string("puts $l_err"); // it gets init to 0.0 at creation, as expected bRubyIsInit=true; } else { bTracePropertyError = false; // Here's what we'll do each "real" time: // -- load the variable values first: RFLOAT(C_l_lay)->value = 69.69; RFLOAT(C_l_src)->value = 69.70; RFLOAT(C_l_err)->value = 0.0; RFLOAT(C_w_lay)->value = 69.69; RFLOAT(C_w_src)->value = 69.70; RFLOAT(C_w_err)->value = 0.0; RFLOAT(C_as_lay)->value = 69.69; RFLOAT(C_as_src)->value = 69.70; RFLOAT(C_as_err)->value = 0.0; RFLOAT(C_ad_lay)->value = 69.69; RFLOAT(C_ad_src)->value = 69.70; RFLOAT(C_ad_err)->value = 0.0; RFLOAT(C_ps_lay)->value = 69.69; RFLOAT(C_ps_src)->value = 69.70; RFLOAT(C_ps_err)->value = 0.0; RFLOAT(C_pd_lay)->value = 69.69; RFLOAT(C_pd_src)->value = 69.70; RFLOAT(C_pd_err)->value = 0.0; // -- Call Ruby function VALUE dontcare = rb_funcall ( rb_cObject, bg_compare__ID, 0/*argc*/ /*, ... (none) */ ); // -- Deal with results if ( RFLOAT(C_l_err)->value>0 || RFLOAT(C_w_err)->value>0 || RFLOAT(C_as_err)->value>0 || RFLOAT(C_ad_err)->value>0 || RFLOAT(C_ps_err)->value>0 || RFLOAT(C_pd_err)->value>0 ) { bTracePropertyError = true; } } } // Ruby__simulated_compare__test() --- Yukihiro Matsumoto wrote: > Hi, > > In message "[PATCH] fixed SIG_SEGV in check_stack() in eval.c" > on 04/05/22, b g writes: > > |I was getting a crash at 'JUMP_TAG(state);' in > |check_stack() in eval.c because prot_tag was NULL. > |The JUMP_TAG macro goes right after prot_tag without > |checking it to be a valid pointer. *CRASH* > | > |Attached is my very simple fix. There's probly a > |better way (I don't know why prot_tag is NULL in this > |case, should it be?), but the patch below works for > |me. > > It's probably caused by prot_tag left uninitialized by the > application. Can you show us the portion of your application code > that inistalize/call Ruby interpreter? > > matz. __________________________________ Do you Yahoo!? Friends. Fun. Try the all-new Yahoo! Messenger. http://messenger.yahoo.com/