Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

segfault when invoking a proc of a method that invokes a proc returned from mrb_proc_new #4028

Closed
robfors opened this issue May 29, 2018 · 0 comments

Comments

@robfors
Copy link
Contributor

robfors commented May 29, 2018

Unfortunately the title is long winded because I can not further narrow down the issue.
I have found a bug.
To summarize the issue, I get a segfault with a program that does the following steps:

  1. create a proc from an irep with mrb_proc_new
  2. assign the proc to a Ruby variable
  3. define a method somewhere that calls the proc (in an .rb file)
  4. use method to get a proc of this method
  5. if I invoke the new proc from within Ruby it will run but segfault before returning
  6. if I invoke the new proc from within c it will run and return with no exception in mrb->exc, but the next time I try to run any code it will segfault

This is how to reproduce:

# app.rb
# this code get turned in to the proc
# it could be empty and still result in the bug, but we will print so we know it runs
puts 'app.rb'
# test_program.rb
def start_app
  $app_proc.call
end

#start_app # calling this directly is not an issue

# method(:start_app).call # calling this here will run the proc and then segfault

puts 'test_program.rb'
// test_stub.c
#include <stdio.h>
#include <mruby.h>
#include <mruby/class.h>
#include <mruby/proc.h>
#include <mruby/variable.h>
#include <mruby/irep.h>
#include <mruby/dump.h>

#include "test_program.c"
#include "app.c"

int main(void)
{
  mrb_state *mrb = mrb_open();
  
  // set up app_proc
  mrb_irep* app_mrb_irep = mrb_read_irep(mrb, app_irep);
  struct RProc* app_proc = mrb_proc_new(mrb, app_mrb_irep);
  mrb_value app_proc_mrb_value = mrb_obj_value(app_proc);
  mrb_gv_set(mrb, mrb_intern_lit(mrb, "$app_proc"), app_proc_mrb_value);
  
  mrb_load_irep(mrb, test_symbol);
  
  // invoke app_proc
  mrb_value code = mrb_str_new(mrb, "method(:start_app)", 20);
  mrb_value return_value = mrb_funcall_argv(mrb, mrb_top_self(mrb), mrb_intern_lit(mrb, "eval"), 1, &code);
  mrb_funcall_argv(mrb, return_value, mrb_intern_lit(mrb, "call"), 0, NULL);
  
  // running any other code after the app_proc will cause problems
  // running "tt = 88" will segfault
  code = mrb_str_new(mrb, "test = 88", 9);
  mrb_funcall_argv(mrb, mrb_top_self(mrb), mrb_intern_lit(mrb, "eval"), 1, &code);
  
  if (mrb->exc)
  {
    mrb_print_error(mrb);
    mrb->exc = NULL;
    return 1;
  }
  
  mrb_close(mrb);
  return 0;
}

Add gems to build_config.rb

conf.gem :core => 'mruby-eval'
conf.gem :core => 'mruby-method'

Compile and run with:

mruby/bin/mrbc -Bapp_irep app.rb
mruby/bin/mrbc -Btest_symbol test_program.rb
gcc -std=c99 -Imruby/include test_stub.c -o test_program mruby/build/host/lib/libmruby.a -lm
./test_program

I get the output:

test_program.rb
app.rb
Segmentation fault

FYI:

  • When I first encountered the bug I was compiling with emscripten and instead of a segfault I would get TypeError: allocation failure
  • This issue is a continuation of irep to proc #4026
  • using mruby at commit 14c2179
@robfors robfors mentioned this issue May 29, 2018
@matz matz closed this as completed in 8392578 Oct 2, 2018
ksekimoto added a commit to ksekimoto/mruby that referenced this issue Jul 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant