いけむランド

はてダからやってきました

ruby master (x86_64-cygwin) がセグっててどうしよう

タイトルのとおりでしかないのであるが、どうバグレポを書けばいいか悩んでるため、とりあえずでメモしておく。

追記 : とりあえず解決しました。

fd0.hatenablog.jp

毎日 AppVeyor で ruby master の CI をしているが、2023/07/18 まで発生していなかった SIGSEGV が 2023/07/19 で発生するようになった。

発生させる ruby のコードは ractor を使った簡易なもの。

# GC.disable # を有効にすると発生しなくなる
def test n
  rs = (1..n).map do |i|
    Ractor.new(i) do |i|
     "r#{i}"
    end
  end
end

30.times.map{|i|
  test i
}

実行結果は以下のとおり。

$ ./miniruby.exe test_ractor_1.rb
test_ractor_1.rb:4: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.
[BUG] Segmentation fault at 0x0000000000000038
ruby 3.3.0dev (2023-10-04T01:25:42Z master d3fd4a6d32) [x86_64-cygwin]

-- Control frame information -----------------------------------------------


-- Threading information ---------------------------------------------------
Total ractor count: 2
Ruby thread count for this ractor: 1

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

* Loaded script: test_ractor_1.rb

* Loaded features:

    0 enumerator.so
    1 thread.rb
    2 fiber.so
    3 rational.so
    4 complex.so
    5 ruby2_keywords.rb

[1]    185 abort (core dumped)  ./miniruby.exe test_ractor_1.rb
$ 

gdb で run すると、毎回違う場所で発生するため、もしかして GC でメモリが壊されるタイミングが毎回異なるのかなと思った。(確証はまったくない。)

$ gdb miniruby.exe
GNU gdb (GDB) (Cygwin 12.1-1) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

(skip)

(gdb) run test_ractor_1.rb
Starting program: /tmp/ruby/miniruby.exe test_ractor_1.rb
[New Thread 3648.0x1a04]
[New Thread 3648.0xf5c]
Error while mapping shared library sections:
`/cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll': not in executable format: file format not recognized

(skip)

test_ractor_1.rb:4: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.
[New Thread 3648.0x2020]
[New Thread 3648.0x2774]
[New Thread 3648.0x213c]
[New Thread 3648.0x1bcc]
[New Thread 3648.0x174]

Thread 6 "miniruby" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 3648.0x2774]
cached_callable_method_entry (klass=0, mid=155) at /tmp/ruby/vm_method.c:1279
1279        struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
(gdb) bt
#0  cached_callable_method_entry (klass=0, mid=155) at /tmp/ruby/vm_method.c:1279
#1  0x0000000100681689 in callable_method_entry_or_negative (klass=0, mid=155, defined_class_ptr=0x7ffa0c758)
    at /tmp/ruby/vm_method.c:1352
#2  0x00000001006817c3 in callable_method_entry (klass=0, mid=155, defined_class_ptr=0x7ffa0c758) at /tmp/ruby/vm_method.c:1389
#3  0x0000000100683ed0 in vm_respond_to (ec=0xa00199fb0, klass=0, obj=123145301134840, id=3233, priv=1) at /tmp/ruby/vm_method.c:2745
#4  0x00000001006863b9 in check_funcall_respond_to (ec=0xa00199fb0, klass=0, recv=123145301134840, mid=3233) at /tmp/ruby/vm_eval.c:622
#5  0x0000000100686746 in rb_check_funcall_default_kw (recv=123145301134840, mid=3233, argc=0, argv=0x0, def=36, kw_splat=0)
    at /tmp/ruby/vm_eval.c:696
#6  0x00000001006866f2 in rb_check_funcall (recv=123145301134840, mid=3233, argc=0, argv=0x0) at /tmp/ruby/vm_eval.c:685
#7  0x000000010053cf1d in convert_type_with_id (val=123145301134840, tname=0x10075f075 <rb_fstring_hash_type+229> "String",
    method=3233, raise=1, index=-1) at object.c:3065
#8  0x000000010053d209 in rb_convert_type_with_id (val=123145301134840, type=5, tname=0x10075f075 <rb_fstring_hash_type+229> "String",
    method=3233) at object.c:3127
#9  0x000000010060103c in rb_str_to_str (str=123145301134840) at string.c:1562
#10 0x00000001006033e9 in rb_string_value (ptr=0x7ffa0ca78) at string.c:2435
#11 0x00000001004efb21 in rb_io_open_descriptor (klass=123145283765840, descriptor=1, mode=196610, path=123145301134840, timeout=4,
    encoding=0x0) at io.c:9207
#12 0x00000001004efc0c in prep_io (fd=1, fmode=196610, klass=123145283765840, path=0x100730571 <utf_prefix+882> "<STDOUT>") at io.c:9230
#13 0x00000001004efd0b in prep_stdio (f=0x7ff976b19e18 <cygwin1!_timezone+1872>, fmode=131074, klass=123145283765840,
    path=0x100730571 <utf_prefix+882> "<STDOUT>") at io.c:9256
#14 0x00000001004efdbf in rb_io_prep_stdout () at io.c:9280
#15 0x0000000100629f92 in thread_start_func_2 (th=0xa00199e30, stack_start=0x7ffa0cd40) at thread.c:671
#16 0x0000000100624ee9 in thread_start_func_1 (th_ptr=0xa000cc2e0) at /tmp/ruby/thread_pthread.c:1119
#17 0x00007ff976887b9f in cygwin1!.getreent () from /usr/bin/cygwin1.dll
#18 0x00007ff976824981 in cygwin1!.assert () from /usr/bin/cygwin1.dll
#19 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

ちなみにこの間の ruby/ruby の差分は以下のとおり。*1

github.com

git bisect で絞ろうとしたのだが、発生したりしなかったりで commit を言ったり来たりしてるうちに途中からわけがわからなくなってしまった...。

*1:前までは SHA 7 桁で見えてたが、branch をまたいでしまったのか見えなくなったため、commit 単位の情報は取れなくなってしまった。