I am running a ruby script through C as follows:
#include <ruby.h>
int main(void) {
ruby_init();
int status;
rb_load_protect(rb_str_new2("./test.rb"), 0, &status);
if (status) {
VALUE rbError = rb_funcall(rb_gv_get("$!"), rb_intern("message"), 0);
printf("%s\n", StringValueCStr(rbError));
}
ruby_finalize();
return status;
}
The ruby script:
1.hello
When I run it now, I get this output:
undefined method `hello' for 1:Integer
This is as expected. I then define this method:
VALUE hello(VALUE self) {
return Qnil;
}
// just after ruby_init()
rb_define_method(rb_cInteger, "hello", hello, 0);
When I run it now, I get
ruby: [BUG] Segmentation fault at 0x00000000000000b0
/* ... */
How can I handle the error here? $!
is nil in this case but I don't know why.
I think you just need to initialise status
:
int status = 0;
It looks like rb_load_protect
sets status if there is an exception, but doesn’t set it to zero if there isn’t, but by passing &status
to it you are suppressing any unitialised variable warnings from the compiler.
What’s happening at the moment is status
starts as some (non-zero) garbage, and doesn’t get set to zero if there is no exception, so the if
block is always executed. However, if there isn’t an exception, then $!
is nil, so calling message
on it results in an unhandled exception which causes the crash.