Skip to content

Conversation

rwstauner
Copy link

Add missing write barriers to address segfaults like this:

#6  0x00007a6207b32556 in sigsegv (sig=11, info=0x7a61cd138870, ctx=0x7a61cd138740) at signal.c:933
#7  0x00007a62074ea520 in <signal handler called> () at /lib/x86_64-linux-gnu/libc.so.6
#8  0x00007a6207b74717 in hash_table_index (key=<optimized out>, tbl=<optimized out>) at /tmp/ruby-build/ruby-3.4.2-pshopify3/id_table.c:132
#9  rb_id_table_lookup (tbl=tbl@entry=0x4, id=id@entry=282833, valp=valp@entry=0x7a611b64d960) at /tmp/ruby-build/ruby-3.4.2-pshopify3/id_table.c:230
#10 0x00007a6207bc04d7 in vm_search_cc (ci=0x450d100140005, klass=134554211975520) at /tmp/ruby-build/ruby-3.4.2-pshopify3/vm_insnhelper.c:2087
#11 rb_vm_search_method_slowpath (ci=0x450d100140005, klass=134554211975520) at /tmp/ruby-build/ruby-3.4.2-pshopify3/vm_insnhelper.c:2189
#12 0x00007a6207bd08ea in vm_search_method_slowpath0 (klass=<optimized out>, cd=<optimized out>, cd_owner=<optimized out>) at /tmp/ruby-build/ruby-3.4.2-pshopify3/vm_insnhelper.c:2210
#13 vm_search_method_fastpath (klass=<optimized out>, cd=<optimized out>, cd_owner=<optimized out>) at /tmp/ruby-build/ruby-3.4.2-pshopify3/vm_insnhelper.c:2271
#14 vm_sendish (method_explorer=<optimized out>, block_handler=<optimized out>, cd=<optimized out>, reg_cfp=<optimized out>, ec=<optimized out>) at /tmp/ruby-build/ruby-3.4.2-pshopify3/vm_insnhelper.c:5960
#15 vm_exec_core (ec=0x4) at /tmp/ruby-build/ruby-3.4.2-pshopify3/insns.def:898
#16 0x00007a6207bd7a1a in rb_vm_exec (ec=0x7a60dc1f39d0) at vm.c:2595
#17 0x00007a6207bd7fc3 in invoke_iseq_block_from_c (me=0x0, is_lambda=<optimized out>, cref=0x0, passed_block_handler=0, kw_splat=<optimized out>, argv=<optimized out>, argc=<optimized out>, self=<optimized out>, captured=<optimized out>, ec=<optimized out>) at vm.c:1625
#18 0x00007a6207bd8a1f in rb_vm_invoke_proc (ec=ec@entry=0x7a60dc1f39d0, proc=<optimized out>, argc=<optimized out>, argv=argv@entry=0x7a611b64de40, kw_splat=<optimized out>, passed_block_handler=<optimized out>) at vm.c:1770
#19 0x00007a6207bdd7d8 in vm_call0_body (ec=0x7a60dc1f39d0, calling=0x7a611b64dd80, argv=0x7a611b64de40) at /tmp/ruby-build/ruby-3.4.2-pshopify3/vm_eval.c:293
#20 0x00007a6207be268e in vm_call0_cc (kw_splat=0, cc=<optimized out>, argv=0x7a611b64de40, argc=1, id=3457, recv=134554228753520, ec=0x7a60dc1f39d0) at /tmp/ruby-build/ruby-3.4.2-pshopify3/vm_eval.c:101
#21 rb_funcallv_scope (scope=CALL_FCALL, argv=0x7a611b64de40, argc=1, mid=3457, recv=134554228753520) at /tmp/ruby-build/ruby-3.4.2-pshopify3/vm_eval.c:1047
#22 rb_funcallv (recv=recv@entry=134554228753520, mid=3457, argc=argc@entry=1, argv=argv@entry=0x7a611b64de40) at /tmp/ruby-build/ruby-3.4.2-pshopify3/vm_eval.c:1062
#23 0x00007a61df04bf46 in grpc_rb_call_credentials_callback (args=args@entry=134555288032520) at /usr/local/ruby/include/ruby-3.4.0/ruby/internal/symbol.h:304

where we end up trying to call methods on T_NONE objects

(gdb) rp klass
T_NONE: $41 = (struct RBasic *) 0x7a6058020160

This was defined in Ruby 2.1 and the gemspec specifies 3.1 as a requirement.
@casperisfine
Copy link

Looking at the crashing func:

static VALUE grpc_rb_call_credentials_callback(VALUE args) {
  VALUE result = rb_hash_new();
  VALUE callback_func = rb_ary_entry(args, 0);
  VALUE callback_args = rb_ary_entry(args, 1);
  VALUE md_ary_obj = rb_ary_entry(args, 2);

  VALUE callback_func_str = rb_funcall(callback_func, rb_intern("to_s"), 0);
  VALUE callback_args_str = rb_funcall(callback_args, rb_intern("to_s"), 0);
  VALUE callback_source_info =
      rb_funcall(callback_func, rb_intern("source_location"), 0);

  grpc_absl_log_str(
      GPR_DEBUG, "GRPC_RUBY: grpc_rb_call_credentials invoking user callback:",
      StringValueCStr(callback_func_str));

  if (callback_source_info != Qnil) {
    VALUE source_filename = rb_ary_entry(callback_source_info, 0);
    VALUE source_line_number =
        rb_funcall(rb_ary_entry(callback_source_info, 1), rb_intern("to_s"), 0);
    grpc_absl_log_str(GPR_DEBUG, "GRPC_RUBY: source_filename: ",
                      StringValueCStr(source_filename));
    grpc_absl_log_str(GPR_DEBUG, "GRPC_RUBY: source_line_number: ",
                      StringValueCStr(source_line_number));
    grpc_absl_log_str(GPR_DEBUG, "GRPC_RUBY: Arguments: ",
                      StringValueCStr(callback_args_str));
  } else {
    grpc_absl_log_str(
        GPR_DEBUG, "(failed to get source filename and line) with arguments: ",
        StringValueCStr(callback_args_str));
  }

  VALUE metadata =
      rb_funcall(callback_func, rb_intern("call"), 1, callback_args);
  grpc_metadata_array* md_ary = NULL;
  TypedData_Get_Struct(md_ary_obj, grpc_metadata_array,
                       &grpc_rb_md_ary_data_type, md_ary);
  grpc_rb_md_ary_convert(metadata, md_ary);
  rb_hash_aset(result, rb_str_new2("metadata"), metadata);
  rb_hash_aset(result, rb_str_new2("status"), INT2NUM(GRPC_STATUS_OK));
  rb_hash_aset(result, rb_str_new2("details"), rb_str_new2(""));
  return result;
}

There ware multiple objects we're calling funcall onto. My advice would be to first use the core dump to check which of these are T_NONE.

From there, look at the code to see which object is responsible for holding them, and where the rb_gc_mark is (potentially it is missing)

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

Successfully merging this pull request may close these issues.

2 participants