いけむランド

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

ruby-3.4.2 で引き続き SIGSEGV の調査をしてた

3 月に「次の回で書きます」と言ってから放置していたけど、ようやく着手して、ちょっと調査が進んだ。が、解決はしていない。

fd0.hatenablog.jp

gdb の操作方法がわからなくて、調査が面倒だと思って、なかなか重い腰が上げられなかったが、最近の AI の力で「gdb といい感じにインタラクティブにやりとりして自動でデバッグしてくれないかな」と思って、ChatGPT に質問したら「今だとまだそれがパパッと簡単にできるやつはなくはないけど、それの準備は面倒だと思うので、gdb の (コマンドと) ログをここに貼ってくれたら、自分が模擬できるよ」みたいなことを言ってきたため、雑にいろいろ質問しながら進めてみた。

途中で再現がわざわざ gem install ではなく、数行でできることを提案してもらえたあたりで、無料枠で使っているのを申し訳なく思ってきた。

# thread_openssl.rb
Thread.new do
  require 'openssl'
end.join

GC.start
sleep 0.1
$ uname -srvmpio
CYGWIN_NT-10.0-22000-ARM64 3.6.3-1.x86_64 2025-06-05 11:45 UTC x86_64 unknown unknown Cygwin
$ /use/bin/ruby -v
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [x86_64-cygwin]
$ gdb -nx /usr/bin/ruby
(gdb) run thread_openssl.rb
:
(snip)
:
Thread 8 "thread_openssl*" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 3968.0x1f48]
0x0000000000000000 in ?? ()
(gdb) where
#0  0x0000000000000000 in ?? ()
#1  0x00007ffe4ad2a0e4 in pthread_testcancel () at /usr/src/debug/cygwin-3.6.3-1/winsup/cygwin/thread.cc:399
#2  pthread_rwlock_wrlock (rwlock=0xa002a9410) at /usr/src/debug/cygwin-3.6.3-1/winsup/cygwin/thread.cc:4352
#3  0x00007ffe4ae0b0d4 in _sigfe () at sigfe.s:35
#4  0x00000003ff54e3f9 in CRYPTO_THREAD_write_lock (lock=<optimized out>) at crypto/threads_pthread.c:110
#5  0x00000003ff541922 in init_thread_remove_handlers (handsin=handsin@entry=0x0) at crypto/initthread.c:178
#6  0x00000003ff541d43 in OPENSSL_thread_stop () at crypto/initthread.c:235
#7  0x00000003ff53fdd3 in DllMain (hinstDLL=<optimized out>, fdwReason=<optimized out>, lpvReserved=<optimized out>) at crypto/dllmain.c:38
#8  0x00007ffe8f2fd6ac in ?? ()
#9  0x00007ffe8f38b590 in ?? ()
#10 0x00007ffe8f38b590 in ?? ()
#11 0x0000000000000000 in ?? ()

(gdb) up
#1  0x00007ffe4ad2a0e4 in pthread_testcancel () at /usr/src/debug/cygwin-3.6.3-1/winsup/cygwin/thread.cc:399
399       return thread;

(gdb) list
394       if (!thread)
395         {
396           thread = pthread_null::get_null_pthread ();
397           thread->set_tls_self_pointer ();
398         }
399       return thread;
400     }
401
402     void
403     pthread::set_tls_self_pointer ()

(gdb) list 394
389
390     pthread *
391     pthread::self ()
392     {
393       pthread *thread = _my_tls.tid;
394       if (!thread)
395         {
396           thread = pthread_null::get_null_pthread ();
397           thread->set_tls_self_pointer ();
398         }

TLS まわりで SIGSEGV が発生しているように見えるが、これ以上追うことは自分の環境では難しいため、バグレポで報告して、他力本願したい。

おまけ

ちなみに追えない理由は _my_tls はマクロで実体は Windows 側の DLL にある関数 (NtCurrentTeb()) に展開されるっぽいのだが、

github.com

#define _my_tls (*((_cygtls *) ((PBYTE) NtCurrentTeb()->Tib.StackBase \
                       - __CYGTLS_PADSIZE__)))

Windows 側の DLL は x86-64 バイナリで、自分は aarch64 (mac の UTM) で動かしているせいか gdb 上で共有ライブラリのセクションを認識できないらしい。

Error while mapping shared library sections:
`/cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll': not in executable format: file format not recognized

よって gdb からシンボル補完もできない → 値を参照できない。実行時に直接アドレスを探すのはさすがに至難の業な気がする。

[追記] ML に投げた。

cygwin.com

[追記2] OpenSSL の方に patch してる test 版をインストールしたら、gem install が突然死しなくなることを確認できた。

cygwin.com