Forum: Ruby How to crash Ruby by not registering global C variable ?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Be13d49ea40add75e564bef96b323caf?d=identicon&s=25 13 (Guest)
on 2007-03-31 14:54
(Received via mailing list)
Hi list,

On page 284 of Pickaxe, 2nd edition there is a passage:

> If you create a Ruby object from C and store it in a C global variable without exporting 
it to Ruby, you must at least tell the garbage collector about it, lest ye be reaped 
inadvertently.

    static VALUE obj;
    /* ... */
    obj = rb_ary_new();
    rb_global_variable(obj);

I would like to reproduce this issue, but don't know how. As far as I
understand, if rb_global_variable(obj) is not called then once the GC
will try to free up garbage memory it will try to destroy obj. GC will
fail and something interesting should happen :)

I tried to implement this bug. While writing this e-mail I started to
think that I misunderstood what Dave Thomas is stating and that I'm
going the wrong way. But here is my code, in case I'm doing something
right:

reg_global.c:

  1 #include <ruby.h>
  2
  3 static VALUE str;
  4
  5 int
  6 main(int argc, char **argv)
  7 {
  8     ruby_init();
  9     ruby_init_loadpath();
 10
 11     /* Create a string variable end export it to ruby */
 12     str = rb_str_new2("FooBar");
 13     rb_define_variable("$value", &str);
 14
 15     rb_require("reg_global.rb");
 16
 17     ruby_finalize();
 18     return 0;
 19 }

reg_global.rb:

  1 # this script should be called from embedded ruby interpreter
  2
  3 def wrapper
  4   p "value: #{$value}, id: #{$value.object_id}"
  5   ObjectSpace.define_finalizer($value, lambda { |id| p "Finalizing
#{id}" })
  6   $value = nil
  7 end
  8
  9 wrapper
 10
 11 ObjectSpace.garbage_collect

When I execute reg_global I see the following (nothing special):

"value: FooBar, id: 76750"
"Finalizing 76750"

I expected Ruby to crash after this line:

 11 ObjectSpace.garbage_collect

Has anyone some hints on how to reproduce the bug described in paragraph
above ?
7f891fbe8e3bae7f9fe375407ce90d9d?d=identicon&s=25 Harold Hausman (Guest)
on 2007-03-31 15:09
(Received via mailing list)
On 3/31/07, 13 <one.three@gmail.com> wrote:
> Hi list,
>
> On page 284 of Pickaxe, 2nd edition there is a passage:
>
> > If you create a Ruby object from C and store it in a C global variable without 
exporting it to Ruby, you must at least tell the garbage collector about it, lest ye be 
reaped inadvertently.
>

Your masochistic behavior scares me a little bit ;), but if I
understand your intention correctly, you don't *actually* want to call
rb_define_variable like you do on line 13... I believe calling that
will cause Ruby to reference the string which is typically a good
thing, but in this case it's whats causing you to fail to see the
fireworks that you seek.

Even if Ruby never references your string, and the garbage collector
does 'reap you inadvertently' you probably wouldn't see the fireworks
until you happened to dereference the 'str' variable later in your C
program, and even then only if the memory in question had been filled
with something interesting in the mean time.

Thats the slippery nature of the descrivbd problem, when you do fall
victim to it it might be tough to debug, because all you're going to
have is *occasionally* an 'str' variable filled with something
strange.

Hope that helps,
-Harold
Be13d49ea40add75e564bef96b323caf?d=identicon&s=25 13 (Guest)
on 2007-03-31 15:37
(Received via mailing list)
Oh, I see! Your answer is what I was looking for. Thanks!

If someone is curious here is this cool piece of code:

  1 #include <ruby.h>
  2
  3 static VALUE str;
  4
  5 int
  6 main(int argc, char **argv)
  7 {
  8     ruby_init();
  9     ruby_init_loadpath();
 10
 11     str = rb_str_new2("FooBar");
 12     /*rb_global_variable(&str);*/ /* Uncomment this if you don't
want SF */
 13
 14     rb_eval_string("GC.start");
 15
 16     /* Boom! Here comes Segmentation fault */
 17     printf("Value: %s\n", StringValuePtr(str));
 18
 19     ruby_finalize();
 20     return 0;
 21 }

--
Martins
This topic is locked and can not be replied to.