Project

General

Profile

Actions

Bug #17643

closed

Ruby 3 embedded - no GC methods?

Added by cfis (Charlie Savage) almost 2 years ago. Updated over 1 year ago.

Status:
Rejected
Priority:
Normal
Target version:
-
ruby -v:
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x64-mingw32]
[ruby-core:<unknown>]

Description

The following code works on Ruby 2.x, but not on Ruby 3.0.0.

// Initialize Ruby VM
int argc = 0;
char* argv = (char*)malloc(1);
argv[0] = 0;
char** pArgv = &argv;

ruby_sysinit(&argc, &pArgv);
ruby_init();
ruby_init_loadpath();

// Try to call GC.start
int state;
VALUE result = rb_eval_string_protect("GC.start", &state);
VALUE err = rb_errinfo();
VALUE rubyMessage = rb_funcall(err, rb_intern("message"), 0);
char* message = RSTRING_PTR(rubyMessage);

message is "undefined method `start' for GC:Module"

This is true for all the GC methods (stop, stress, etc). Note if you create a Ruby script that contains GC.start and run it using the Ruby interpreter all is well.

Is there some new special way Ruby 3 needs to be embedded?

Note I tested this on mingw, MSVC and gcc (Fedora). All the same. Like I said above, this code works fine on Ruby 2.7 and earlier.


Files

Screenshot 2021-04-02 013926.png (194 KB) Screenshot 2021-04-02 013926.png cfis (Charlie Savage), 04/02/2021 08:40 AM
Screenshot 2021-04-02 013926.png (194 KB) Screenshot 2021-04-02 013926.png cfis (Charlie Savage), 04/02/2021 08:40 AM
Screenshot 2021-04-02 013926.png (194 KB) Screenshot 2021-04-02 013926.png cfis (Charlie Savage), 04/02/2021 08:40 AM
Actions #1

Updated by cfis (Charlie Savage) almost 2 years ago

  • Description updated (diff)
Actions #2

Updated by cfis (Charlie Savage) almost 2 years ago

  • Description updated (diff)
Actions #3

Updated by cfis (Charlie Savage) almost 2 years ago

  • Description updated (diff)
Actions #4

Updated by jeremyevans0 (Jeremy Evans) almost 2 years ago

  • Status changed from Open to Assigned
  • Assignee set to nobu (Nobuyoshi Nakada)

I've confirmed this behavior, and bisected it to 2c3c6c96cfc31eb387c643990375e6e1d67b409d. Looks like it could be fixed by calling rb_call_builtin_inits(), but that doesn't appear to be exported. @nobu (Nobuyoshi Nakada) is that correct and is this expected? Should rb_call_builtin_inits() be exported, or should another function be called?

Actions #5

Updated by cfis (Charlie Savage) almost 2 years ago

Thanks for tracking this down Jeremy!

This would be very helpful to have back. I'm modernizing Rice (https://github.com/cfis/rice/tree/dev) and being able to call GC.start from Ruby code (versus rb_gc_start) as well as setting GC.stress are quite handy for verifying mark/free are being handled correctly.

Updated by cfis (Charlie Savage) almost 2 years ago

Just following up. nobu any thoughts? I don't see any way of working around this currently when embedding Ruby.

Updated by nobu (Nobuyoshi Nakada) almost 2 years ago

  • Status changed from Assigned to Rejected

You don't call ruby_options.

And the argv made in this part is wrong.

int argc = 0;
char* argv = (char*)malloc(1);
argv[0] = 0;
char** pArgv = &argv;

Updated by cfis (Charlie Savage) over 1 year ago

@nobu (Nobuyoshi Nakada) - Sorry that I missed your feedback.

I updated the code to call ruby_options, but that just hangs the interpreter. It thinks it is going to run a ruby script, but that is not correct. I have attached a screenshot of the call stack.

What I want to do is initialize the interpreter so I can later run code in it. As part of the initialization I'd like to set GC.stress to true.

I updated the embedding code to look like this (copied from Ruby's main function):

    int argc = 0;
    char* argv = nullptr;
    char** pArgv = &argv;

    ruby_sysinit(&argc, &pArgv);
    {
      RUBY_INIT_STACK;
      ruby_init();
      ruby_run_node(ruby_options(argc, pArgv));
    }

    initialized__ = true; // <----- this is never called

That doesn't work. Could you point me in the direction of what does work? Thanks!

Updated by nobu (Nobuyoshi Nakada) over 1 year ago

No arguments means reading the script from stdin.
You need to give a script name or an -e option.

Updated by cfis (Charlie Savage) over 1 year ago

I don't want to do either of those things. Instead I would like to embed Ruby into a C++ program and then use it run tests.

Specifically, this is for Rice. The embed Ruby code:

https://github.com/jasonroelofs/rice/blob/master/test/embed_ruby.cpp

Then tests, for example:

https://github.com/jasonroelofs/rice/blob/master/test/test_Array.cpp

The reason I'd like to have access to the GC methods is to enable GC stress. That helps verify that Rice is correctly correctly managing memory when integrating with the interpreter.

This used to work fine in Ruby 2.x but not 3.x. I believe this is a regression and should be fixed.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0