mruby: SEGFAULT Issue Related to Fiber Usage in ngx_mruby Development

mruby version:3.2.0

Hello. I am developing with ngx_mruby and I have encountered a SEGV issue related to Fiber and would like to consult with you about it.

  mrb_value fiber_class = mrb_obj_value(mrb_class_get(mrb, "Fiber"));
  handler_proc = mrb_obj_value(mrb_closure_new(mrb, rproc->body.irep));
  if (mrb->exc) {
    ...
  }

  fiber_proc = (mrb_value *)ngx_palloc(r->pool, sizeof(mrb_value));
  *fiber_proc = mrb_funcall_with_block(mrb, fiber_class, mrb_intern_cstr(mrb, "new"), 0, NULL, handler_proc);
  ...

  handler_result = mrb_fiber_resume(mrb, *fiber_proc, 0, NULL);

A SEGV occurs when performing operations such as redirects in Nginx, moving back and forth between the Nginx context and the mruby context. The error appears at the following location.

Program received signal SIGSEGV, Segmentation fault.
0x00005555557a1ae3 in fiber_switch (mrb=0x555555ad01c0, self=..., len=0, a=0x0, resume=true, vmexec=true) at /home/pyama/src/github.com/matsumotory/ngx_mruby/mruby/mrbgems/mruby-fiber/src/fiber.c:260
260     value = c->stbase[0] = MRB_PROC_ENV(c->cibase->proc)->stack[0];
  1. Here is the state during the first execution. At this point, c->cibase->proc->flags equals 1536.
com/matsumotory/ngx_mruby/src/http/ngx_http_mruby_module.c:841
841    if (mrb_test(ngx_mrb_start_fiber(r, state->mrb, code->proc, mrb_result))) {
(gdb) p *code
$40 = {code = {
  file = 0x555555b9bb20 "Nginx::Request.new.headers_out[\"Server\"] = \"global_ngx_mruby\"; Nginx.return Nginx::DECLINED",
  string = 0x555555b9bb20 "Nginx::Request.new.headers_out[\"Server\"] = \"global_ngx_mruby\"; Nginx.return Nginx::DECLINED"},
 code_type = NGX_MRB_CODE_TYPE_STRING, n = 0, cache = 1, proc = 0x555555b35500, ctx = 0x555555b8f0e0}


ory/ngx_mruby/mruby/mrbgems/mruby-fiber/src/fiber.c:260
260     value = c->stbase[0] = MRB_PROC_ENV(c->cibase->proc)->stack[0];
(gdb) p c->cibase->proc->flags
$42 = 1536
  1. For the second execution, c->cibase->proc->flags equals 512.
com/matsumotory/ngx_mruby/src/http/ngx_http_mruby_module.c:841
841    if (mrb_test(ngx_mrb_start_fiber(r, state->mrb, code->proc, mrb_result))) {
(gdb) p *code
$45 = {code = {
  file = 0x555555b9bb20 "Nginx::Request.new.headers_out[\"Server\"] = \"global_ngx_mruby\"; Nginx.return Nginx::DECLINED",
  string = 0x555555b9bb20 "Nginx::Request.new.headers_out[\"Server\"] = \"global_ngx_mruby\"; Nginx.return Nginx::DECLINED"},
 code_type = NGX_MRB_CODE_TYPE_STRING, n = 0, cache = 1, proc = 0x555555b35500, ctx = 0x555555b8f0e0}
(gdb) c
Continuing.

Breakpoint 2, fiber_switch (mrb=0x555555ad01c0, self=..., len=0, a=0x0, resume=true, vmexec=true) at /home/pyama/src/github.com/matsumotory/ngx_mruby/mruby/mrbgems/mruby-fiber/src/fiber.c:260
260     value = c->stbase[0] = MRB_PROC_ENV(c->cibase->proc)->stack[0];
(gdb) p c->cibase->proc->flags
$46 = 512

As a result, it seems that the following process is diverged and NULL is returned.

https://github.com/mruby/mruby/blob/master/include/mruby/proc.h#L69

#define MRB_PROC_ORPHAN 512
#define MRB_PROC_ORPHAN_P(p) (((p)->flags & MRB_PROC_ORPHAN) != 0)
#define MRB_PROC_ENVSET 1024
#define MRB_PROC_ENV_P(p) (((p)->flags & MRB_PROC_ENVSET) != 0)
#define MRB_PROC_ENV(p) (MRB_PROC_ENV_P(p) ? (p)->e.env : NULL)

If you have any information necessary to resolve this issue, please let me know

About this issue

  • Original URL
  • State: closed
  • Created 9 months ago
  • Comments: 27 (27 by maintainers)

Commits related to this issue

Most upvoted comments

Thank you for your assistance. I tried the patch you provided, and it worked perfectly. I really appreciate it. Please have a great weekend.