Project

General

Profile

Actions

Bug #18140

closed

GC prematurely frees objects from implicit #to_ary conversion, leading to segfault

Added by jhaberman (Josh Haberman) over 2 years ago. Updated over 2 years ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:105099]

Description

The following repro crashes in every version of Ruby starting from 2.5.0 and including the latest (3.0.2):

// test_ext.c

#include "ruby.h"

VALUE cFoo; 

// Foo

typedef struct {
  int dummy;
} Foo;

static void Foo_free(void* _self) {
  fprintf(stderr, "Foo_free(%p)\n", _self);
  xfree(_self);
}

static rb_data_type_t Foo_type = {
  "Foo",
  {NULL, Foo_free, NULL },
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
};

static VALUE Foo_alloc(VALUE klass) {
  Foo* _self = ALLOC(Foo);
  fprintf(stderr, "Foo_alloc(%p)\n", _self);
  return TypedData_Wrap_Struct(klass, &Foo_type, _self);
}

// Bar

typedef struct {
  int dummy;
} Bar;

static void Bar_free(void* _self) {
  fprintf(stderr, "Bar_free(%p)\n", _self);
  xfree(_self);
}

static rb_data_type_t Bar_type = {
  "Bar",
  {NULL, Bar_free, NULL },
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
};

static VALUE Bar_alloc(VALUE klass) {
  Bar* bar = ALLOC(Bar);
  return TypedData_Wrap_Struct(klass, &Bar_type, bar);
}

VALUE Bar_to_ary(VALUE _self) {
  fprintf(stderr, "Bar_to_ary() begin\n");
  VALUE ary = rb_ary_new2(2);
  rb_ary_push(ary, Foo_alloc(cFoo));
  rb_ary_push(ary, Foo_alloc(cFoo));
  rb_ary_push(ary, Foo_alloc(cFoo));
  fprintf(stderr, "Bar_to_ary() end\n");
  return ary;
}

void Init_test_ext() {
  cFoo = rb_define_class("Foo", rb_cObject);
  rb_gc_register_address(&cFoo);
  rb_define_alloc_func(cFoo, Foo_alloc);

  VALUE bar = rb_define_class("Bar", rb_cObject);
  rb_define_alloc_func(bar, Bar_alloc);
  rb_define_method(bar, "to_ary", Bar_to_ary, 0);
}
#!/usr/bin/ruby
    
require 'mkmf'
    
$objs = ["test_ext.o"]
    
create_makefile("test_ext")
// test.rb
require "test_ext"

GC.stress = true

arr = [nil]
STDERR.puts("Bar.new")
bar = Bar.new
STDERR.puts("concat")
arr.concat(bar)
STDERR.puts("concat done")

Output is:

Bar.new
concat
Bar_to_ary() begin
Foo_alloc(0x55580d816360)
Foo_alloc(0x55580d993fe0)
Foo_alloc(0x55580d8f58e0)
Bar_to_ary() end
Foo_free(0x55580d8f58e0)
Foo_free(0x55580d993fe0)
Foo_free(0x55580d816360)
<OBJ_INFO:gc_mark_ptr@gc.c:6113> 0x000055580d997e50 [2 M   ] T_NONE 
test.rb:11: [BUG] try to mark T_NONE object
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0002 p:0081 s:0009 E:002120 EVAL   test.rb:11 [FINISH]
c:0001 p:0000 s:0003 E:000ab0 (none) [FINISH]

-- Ruby level backtrace information ----------------------------------------
test.rb:11:in `<main>'

-- C level backtrace information -------------------------------------------
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(rb_print_backtrace+0x11) [0x55580d294925] vm_dump.c:758
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(rb_vm_bugreport) vm_dump.c:998
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(bug_report_end+0x0) [0x55580d33a3ad] error.c:763
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(rb_bug_without_die) error.c:763
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(die+0x0) [0x55580d09584c] error.c:771
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(rb_bug) error.c:773
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(gc_mark_ptr+0x140) [0x55580d0b6d10] gc.c:6114
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(gc_mark_children+0x88b) [0x55580d0b84eb] gc.c:6147
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(gc_mark_stacked_objects+0x3f) [0x55580d0b9007] gc.c:6467
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(gc_mark_stacked_objects_incremental) gc.c:6501
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(gc_marks_rest) gc.c:7444
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(gc_rest+0xc0) [0x55580d0b9e90] gc.c:8343
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(gc_rest+0x8) [0x55580d0b9f70] gc.c:8215
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(garbage_collect) gc.c:8204
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(newobj_slowpath+0x143) [0x55580d0bd413] gc.c:2257
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(newobj_slowpath_wb_protected) gc.c:2284
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(newobj_of0+0x5) [0x55580d0bd4b5] gc.c:2323
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(newobj_of_cr) gc.c:2340
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(rb_ec_wb_protected_newobj_of) gc.c:2362
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(memcpy+0x0) [0x55580d20705f] string.c:1548
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(ruby_nonempty_memcpy) ./include/ruby/internal/memory.h:269
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(ruby_nonempty_memcpy) ./include/ruby/internal/memory.h:266
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(str_duplicate_setup) string.c:1563
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(ec_str_duplicate) string.c:1595
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(rb_ec_str_resurrect) string.c:1622
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(vm_exec_core+0xdee) [0x55580d28208e] insns.def:366
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(rb_vm_exec+0x17f) [0x55580d2773cf] vm.c:2163
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(rb_ec_exec_node+0xc6) [0x55580d095d96] eval.c:317
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(ruby_run_node+0x49) [0x55580d09a739] eval.c:375
/usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby(main+0x5b) [0x55580d095b4b] error.c:3076

-- Other runtime information -----------------------------------------------

* Loaded script: test.rb

* Loaded features:

    0 enumerator.so
    1 thread.rb
    2 rational.so
    3 complex.so
    4 ruby2_keywords.rb
    5 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/encdb.so
    6 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/trans/transdb.so
    7 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/rbconfig.rb
    8 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/compatibility.rb
    9 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/defaults.rb
   10 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/deprecate.rb
   11 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/errors.rb
   12 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/exceptions.rb
   13 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/basic_specification.rb
   14 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/stub_specification.rb
   15 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/text.rb
   16 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/user_interaction.rb
   17 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/specification_policy.rb
   18 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/util/list.rb
   19 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/platform.rb
   20 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/version.rb
   21 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/requirement.rb
   22 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/specification.rb
   23 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/util.rb
   24 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/dependency.rb
   25 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/core_ext/kernel_gem.rb
   26 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/monitor.so
   27 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/monitor.rb
   28 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb
   29 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/core_ext/kernel_warn.rb
   30 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems.rb
   31 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/rubygems/path_support.rb
   32 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/version.rb
   33 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/core_ext/name_error.rb
   34 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/levenshtein.rb
   35 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/jaro_winkler.rb
   36 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/spell_checker.rb
   37 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb
   38 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb
   39 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/spell_checkers/name_error_checkers.rb
   40 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/spell_checkers/method_name_checker.rb
   41 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/spell_checkers/key_error_checker.rb
   42 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/spell_checkers/null_checker.rb
   43 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/tree_spell_checker.rb
   44 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/spell_checkers/require_path_checker.rb
   45 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean/formatters/plain_formatter.rb
   46 /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/did_you_mean.rb
   47 /usr/local/google/home/haberman/code/protobuf/ruby/test_repro/test_ext.so

* Process memory map:

55580d068000-55580d090000 r--p 00000000 fd:01 36594071                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby
55580d090000-55580d347000 r-xp 00028000 fd:01 36594071                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby
55580d347000-55580d452000 r--p 002df000 fd:01 36594071                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby
55580d453000-55580d459000 r--p 003ea000 fd:01 36594071                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby
55580d459000-55580d45a000 rw-p 003f0000 fd:01 36594071                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby
55580d45a000-55580d46b000 rw-p 00000000 00:00 0 
55580d60d000-55580d9e5000 rw-p 00000000 00:00 0                          [heap]
7fbaca742000-7fbaca904000 r--s 00000000 fd:01 33948006                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fbaca904000-7fbaccc1c000 r--s 00000000 fd:01 36594071                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/bin/ruby
7fbaccc1c000-7fbaccc1f000 r--p 00000000 fd:01 33948594                   /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
7fbaccc1f000-7fbaccc30000 r-xp 00003000 fd:01 33948594                   /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
7fbaccc30000-7fbaccc34000 r--p 00014000 fd:01 33948594                   /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
7fbaccc34000-7fbaccc35000 r--p 00017000 fd:01 33948594                   /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
7fbaccc35000-7fbaccc36000 rw-p 00018000 fd:01 33948594                   /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
7fbaccc56000-7fbaccc57000 ---p 00000000 00:00 0 
7fbaccc57000-7fbacccf8000 rw-p 00000000 00:00 0 
7fbacccf8000-7fbacccf9000 ---p 00000000 00:00 0 
7fbacccf9000-7fbaccd9a000 rw-p 00000000 00:00 0 
7fbaccd9a000-7fbaccd9b000 ---p 00000000 00:00 0 
7fbaccd9b000-7fbacce3c000 rw-p 00000000 00:00 0 
7fbacce3c000-7fbacce3d000 ---p 00000000 00:00 0 
7fbacce3d000-7fbaccede000 rw-p 00000000 00:00 0 
7fbaccede000-7fbaccedf000 ---p 00000000 00:00 0 
7fbaccedf000-7fbaccf80000 rw-p 00000000 00:00 0 
7fbaccf80000-7fbaccf81000 ---p 00000000 00:00 0 
7fbaccf81000-7fbacd022000 rw-p 00000000 00:00 0 
7fbacd022000-7fbacd023000 ---p 00000000 00:00 0 
7fbacd023000-7fbacd0c4000 rw-p 00000000 00:00 0 
7fbacd0c4000-7fbacd0c5000 ---p 00000000 00:00 0 
7fbacd0c5000-7fbacd166000 rw-p 00000000 00:00 0 
7fbacd166000-7fbacd167000 ---p 00000000 00:00 0 
7fbacd167000-7fbacd208000 rw-p 00000000 00:00 0 
7fbacd208000-7fbacd209000 ---p 00000000 00:00 0 
7fbacd209000-7fbacd2aa000 rw-p 00000000 00:00 0 
7fbacd2aa000-7fbacd2ab000 ---p 00000000 00:00 0 
7fbacd2ab000-7fbacd34c000 rw-p 00000000 00:00 0 
7fbacd34c000-7fbacd34d000 ---p 00000000 00:00 0 
7fbacd34d000-7fbacd3ee000 rw-p 00000000 00:00 0 
7fbacd3ee000-7fbacd3ef000 ---p 00000000 00:00 0 
7fbacd3ef000-7fbacd490000 rw-p 00000000 00:00 0 
7fbacd490000-7fbacd491000 ---p 00000000 00:00 0 
7fbacd491000-7fbacd532000 rw-p 00000000 00:00 0 
7fbacd532000-7fbacd533000 ---p 00000000 00:00 0 
7fbacd533000-7fbacd5d4000 rw-p 00000000 00:00 0 
7fbacd5d4000-7fbacd5d5000 ---p 00000000 00:00 0 
7fbacd5d5000-7fbacd676000 rw-p 00000000 00:00 0 
7fbacd676000-7fbacd677000 ---p 00000000 00:00 0 
7fbacd677000-7fbacd718000 rw-p 00000000 00:00 0 
7fbacd718000-7fbacd719000 ---p 00000000 00:00 0 
7fbacd719000-7fbacd7ba000 rw-p 00000000 00:00 0 
7fbacd7ba000-7fbacd7bb000 ---p 00000000 00:00 0 
7fbacd7bb000-7fbacd85c000 rw-p 00000000 00:00 0 
7fbacd85c000-7fbacd85d000 ---p 00000000 00:00 0 
7fbacd85d000-7fbacd8fe000 rw-p 00000000 00:00 0 
7fbacd8fe000-7fbacd8ff000 ---p 00000000 00:00 0 
7fbacd8ff000-7fbacd9a0000 rw-p 00000000 00:00 0 
7fbacd9a0000-7fbacd9a1000 ---p 00000000 00:00 0 
7fbacd9a1000-7fbacda42000 rw-p 00000000 00:00 0 
7fbacda42000-7fbacda43000 ---p 00000000 00:00 0 
7fbacda43000-7fbacdae4000 rw-p 00000000 00:00 0 
7fbacdae4000-7fbacdae5000 ---p 00000000 00:00 0 
7fbacdae5000-7fbacdb86000 rw-p 00000000 00:00 0 
7fbacdb86000-7fbacdb87000 ---p 00000000 00:00 0 
7fbacdb87000-7fbacdc28000 rw-p 00000000 00:00 0 
7fbacdc28000-7fbacdc29000 ---p 00000000 00:00 0 
7fbacdc29000-7fbacdcca000 rw-p 00000000 00:00 0 
7fbacdcca000-7fbacdccb000 ---p 00000000 00:00 0 
7fbacdccb000-7fbacdd6c000 rw-p 00000000 00:00 0 
7fbacdd6c000-7fbacdd6d000 ---p 00000000 00:00 0 
7fbacdd6d000-7fbacde0e000 rw-p 00000000 00:00 0 
7fbacde0e000-7fbacde0f000 ---p 00000000 00:00 0 
7fbacde0f000-7fbacdeb0000 rw-p 00000000 00:00 0 
7fbacdeb0000-7fbacdeb1000 ---p 00000000 00:00 0 
7fbacdeb1000-7fbacdf52000 rw-p 00000000 00:00 0 
7fbacdf52000-7fbacdf53000 ---p 00000000 00:00 0 
7fbacdf53000-7fbacdff4000 rw-p 00000000 00:00 0 
7fbacdff4000-7fbacdff5000 ---p 00000000 00:00 0 
7fbacdff5000-7fbad0201000 rw-p 00000000 00:00 0 
7fbad0201000-7fbad04e8000 r--p 00000000 fd:01 33030163                   /usr/lib/locale/locale-archive
7fbad04e8000-7fbad04ea000 rw-p 00000000 00:00 0 
7fbad04ea000-7fbad050f000 r--p 00000000 fd:01 33948006                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fbad050f000-7fbad065a000 r-xp 00025000 fd:01 33948006                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fbad065a000-7fbad06a4000 r--p 00170000 fd:01 33948006                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fbad06a4000-7fbad06a5000 ---p 001ba000 fd:01 33948006                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fbad06a5000-7fbad06a8000 r--p 001ba000 fd:01 33948006                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fbad06a8000-7fbad06ab000 rw-p 001bd000 fd:01 33948006                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fbad06ab000-7fbad06af000 rw-p 00000000 00:00 0 
7fbad06af000-7fbad06be000 r--p 00000000 fd:01 33948010                   /usr/lib/x86_64-linux-gnu/libm-2.31.so
7fbad06be000-7fbad0758000 r-xp 0000f000 fd:01 33948010                   /usr/lib/x86_64-linux-gnu/libm-2.31.so
7fbad0758000-7fbad07f1000 r--p 000a9000 fd:01 33948010                   /usr/lib/x86_64-linux-gnu/libm-2.31.so
7fbad07f1000-7fbad07f2000 r--p 00141000 fd:01 33948010                   /usr/lib/x86_64-linux-gnu/libm-2.31.so
7fbad07f2000-7fbad07f3000 rw-p 00142000 fd:01 33948010                   /usr/lib/x86_64-linux-gnu/libm-2.31.so
7fbad07f3000-7fbad07f5000 rw-p 00000000 00:00 0 
7fbad07f5000-7fbad07f7000 r--p 00000000 fd:01 33949537                   /usr/lib/x86_64-linux-gnu/libcrypt.so.1.1.0
7fbad07f7000-7fbad080c000 r-xp 00002000 fd:01 33949537                   /usr/lib/x86_64-linux-gnu/libcrypt.so.1.1.0
7fbad080c000-7fbad0826000 r--p 00017000 fd:01 33949537                   /usr/lib/x86_64-linux-gnu/libcrypt.so.1.1.0
7fbad0826000-7fbad0827000 r--p 00030000 fd:01 33949537                   /usr/lib/x86_64-linux-gnu/libcrypt.so.1.1.0
7fbad0827000-7fbad0828000 rw-p 00031000 fd:01 33949537                   /usr/lib/x86_64-linux-gnu/libcrypt.so.1.1.0
7fbad0828000-7fbad0830000 rw-p 00000000 00:00 0 
7fbad0830000-7fbad0831000 r--p 00000000 fd:01 33948008                   /usr/lib/x86_64-linux-gnu/libdl-2.31.so
7fbad0831000-7fbad0833000 r-xp 00001000 fd:01 33948008                   /usr/lib/x86_64-linux-gnu/libdl-2.31.so
7fbad0833000-7fbad0834000 r--p 00003000 fd:01 33948008                   /usr/lib/x86_64-linux-gnu/libdl-2.31.so
7fbad0834000-7fbad0835000 r--p 00003000 fd:01 33948008                   /usr/lib/x86_64-linux-gnu/libdl-2.31.so
7fbad0835000-7fbad0836000 rw-p 00004000 fd:01 33948008                   /usr/lib/x86_64-linux-gnu/libdl-2.31.so
7fbad0836000-7fbad0841000 r--p 00000000 fd:01 33948804                   /usr/lib/x86_64-linux-gnu/libgmp.so.10.4.1
7fbad0841000-7fbad089d000 r-xp 0000b000 fd:01 33948804                   /usr/lib/x86_64-linux-gnu/libgmp.so.10.4.1
7fbad089d000-7fbad08b4000 r--p 00067000 fd:01 33948804                   /usr/lib/x86_64-linux-gnu/libgmp.so.10.4.1
7fbad08b4000-7fbad08b5000 ---p 0007e000 fd:01 33948804                   /usr/lib/x86_64-linux-gnu/libgmp.so.10.4.1
7fbad08b5000-7fbad08b6000 r--p 0007e000 fd:01 33948804                   /usr/lib/x86_64-linux-gnu/libgmp.so.10.4.1
7fbad08b6000-7fbad08b7000 rw-p 0007f000 fd:01 33948804                   /usr/lib/x86_64-linux-gnu/libgmp.so.10.4.1
7fbad08b7000-7fbad08ba000 r--p 00000000 fd:01 33948060                   /usr/lib/x86_64-linux-gnu/librt-2.31.so
7fbad08ba000-7fbad08be000 r-xp 00003000 fd:01 33948060                   /usr/lib/x86_64-linux-gnu/librt-2.31.so
7fbad08be000-7fbad08bf000 r--p 00007000 fd:01 33948060                   /usr/lib/x86_64-linux-gnu/librt-2.31.so
7fbad08bf000-7fbad08c0000 ---p 00008000 fd:01 33948060                   /usr/lib/x86_64-linux-gnu/librt-2.31.so
7fbad08c0000-7fbad08c1000 r--p 00008000 fd:01 33948060                   /usr/lib/x86_64-linux-gnu/librt-2.31.so
7fbad08c1000-7fbad08c2000 rw-p 00009000 fd:01 33948060                   /usr/lib/x86_64-linux-gnu/librt-2.31.so
7fbad08c2000-7fbad08c9000 r--p 00000000 fd:01 33948052                   /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
7fbad08c9000-7fbad08d9000 r-xp 00007000 fd:01 33948052                   /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
7fbad08d9000-7fbad08de000 r--p 00017000 fd:01 33948052                   /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
7fbad08de000-7fbad08df000 r--p 0001b000 fd:01 33948052                   /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
7fbad08df000-7fbad08e0000 rw-p 0001c000 fd:01 33948052                   /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
7fbad08e0000-7fbad08e4000 rw-p 00000000 00:00 0 
7fbad08e4000-7fbad08e7000 r--p 00000000 fd:01 33949871                   /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
7fbad08e7000-7fbad08f8000 r-xp 00003000 fd:01 33949871                   /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
7fbad08f8000-7fbad08fe000 r--p 00014000 fd:01 33949871                   /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
7fbad08fe000-7fbad08ff000 ---p 0001a000 fd:01 33949871                   /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
7fbad08ff000-7fbad0900000 r--p 0001a000 fd:01 33949871                   /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
7fbad0900000-7fbad0901000 rw-p 0001b000 fd:01 33949871                   /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
7fbad0905000-7fbad0906000 r--p 00000000 fd:01 38420503                   /usr/local/google/home/haberman/code/protobuf/ruby/test_repro/test_ext.so
7fbad0906000-7fbad0907000 r-xp 00001000 fd:01 38420503                   /usr/local/google/home/haberman/code/protobuf/ruby/test_repro/test_ext.so
7fbad0907000-7fbad0908000 r--p 00002000 fd:01 38420503                   /usr/local/google/home/haberman/code/protobuf/ruby/test_repro/test_ext.so
7fbad0908000-7fbad0909000 r--p 00002000 fd:01 38420503                   /usr/local/google/home/haberman/code/protobuf/ruby/test_repro/test_ext.so
7fbad0909000-7fbad090a000 rw-p 00003000 fd:01 38420503                   /usr/local/google/home/haberman/code/protobuf/ruby/test_repro/test_ext.so
7fbad090a000-7fbad090b000 r--p 00000000 fd:01 36723526                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/monitor.so
7fbad090b000-7fbad090c000 r-xp 00001000 fd:01 36723526                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/monitor.so
7fbad090c000-7fbad090d000 r--p 00002000 fd:01 36723526                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/monitor.so
7fbad090d000-7fbad090e000 r--p 00002000 fd:01 36723526                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/monitor.so
7fbad090e000-7fbad090f000 rw-p 00003000 fd:01 36723526                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/monitor.so
7fbad090f000-7fbad0910000 r--p 00000000 fd:01 36978765                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/trans/transdb.so
7fbad0910000-7fbad0912000 r-xp 00001000 fd:01 36978765                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/trans/transdb.so
7fbad0912000-7fbad0913000 r--p 00003000 fd:01 36978765                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/trans/transdb.so
7fbad0913000-7fbad0914000 r--p 00003000 fd:01 36978765                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/trans/transdb.so
7fbad0914000-7fbad0915000 rw-p 00004000 fd:01 36978765                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/trans/transdb.so
7fbad0915000-7fbad0916000 r--p 00000000 fd:01 36983946                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/encdb.so
7fbad0916000-7fbad0917000 r-xp 00001000 fd:01 36983946                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/encdb.so
7fbad0917000-7fbad0918000 r--p 00002000 fd:01 36983946                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/encdb.so
7fbad0918000-7fbad0919000 r--p 00002000 fd:01 36983946                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/encdb.so
7fbad0919000-7fbad091a000 rw-p 00003000 fd:01 36983946                   /usr/local/google/home/haberman/.rubies/ruby-3.0.2/lib/ruby/3.0.0/x86_64-linux/enc/encdb.so
7fbad091a000-7fbad0921000 r--s 00000000 fd:01 33958468                   /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
7fbad0921000-7fbad0923000 rw-p 00000000 00:00 0 
7fbad0923000-7fbad0924000 r--p 00000000 fd:01 33947998                   /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fbad0924000-7fbad0944000 r-xp 00001000 fd:01 33947998                   /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fbad0944000-7fbad094c000 r--p 00021000 fd:01 33947998                   /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fbad094d000-7fbad094e000 r--p 00029000 fd:01 33947998                   /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fbad094e000-7fbad094f000 rw-p 0002a000 fd:01 33947998                   /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fbad094f000-7fbad0950000 rw-p 00000000 00:00 0 
7ffd498ac000-7ffd4a0ab000 rw-p 00000000 00:00 0                          [stack]
7ffd4a193000-7ffd4a197000 r--p 00000000 00:00 0                          [vvar]
7ffd4a197000-7ffd4a199000 r-xp 00000000 00:00 0                          [vdso]

Files

0001-Guard-array-when-appending.patch (728 Bytes) 0001-Guard-array-when-appending.patch tenderlovemaking (Aaron Patterson), 09/01/2021 12:07 AM

Updated by jhaberman (Josh Haberman) over 2 years ago

I should mention that the SEGV goes away if you explicitly convert to array first, instead of letting Array#concat do it implicitly:

require "test_ext"

GC.stress = true

arr = [nil]
STDERR.puts("Bar.new")
bar = Bar.new
STDERR.puts("concat")
arr.concat(bar.to_ary)  # Doesn't crash
STDERR.puts("concat done")

So it seems to be related to the way that Array#concat is implicitly converting the object to an array with #to_ary. The implementation of Array#concat doesn't appear to be properly GC-rooting the temporary array in this case.

Updated by tenderlovemaking (Aaron Patterson) over 2 years ago

I think we need a GC guard in ary_append. We're calling rb_ary_splice with the underlying array pointer. The compiler probably optimized away writing y anywhere in the stack so the GC doesn't see it. Explicitly casting to to_ary would put the array on the Ruby stack and the GC can see it.

I've attached a patch that fixes the issue for me (also compiling without optimizations fixes it, which definitely makes it seem like a compiler optimization problem).

Updated by jhaberman (Josh Haberman) over 2 years ago

Amazingly quick confirmation, diagnosis, and fix. Thank you!

Updated by stanhu (Stan Hu) over 2 years ago

Thanks for the quick patch, Aaron! Thanks, Josh, for taking the initial repro step and boiling it down even further.

This explains why I didn't see the problem when I compiled Ruby with -O0.

Actions #5

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

  • Backport changed from 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN to 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED
Actions #6

Updated by tenderlovemaking (Aaron Patterson) over 2 years ago

  • Status changed from Open to Closed

Applied in changeset git|cd4f5b13228879d954fa97b6aa479c4a5ef4fb0a.


Guard array when appending

This prevents early collection of the array. The GC doesn't see the
array on the stack when Ruby is compiled with optimizations enabled

[ruby-core:105099] [Bug #18140]

Updated by nagachika (Tomoyuki Chikanaga) over 2 years ago

  • Backport changed from 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED to 2.6: REQUIRED, 2.7: REQUIRED, 3.0: DONE

ruby_3_0 92846db6861eed324288819157e6c7722fc62fc2 merged revision(s) cd4f5b13228879d954fa97b6aa479c4a5ef4fb0a,8db269edb3550a85dfab9b193ea115ca36912ced,ab63f6d8543903f177c46634f38e5428655f003b.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0