いけむランド

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

テスト版ですが ruby-3.4.2 をアップロードしました

タイトルに n 月号とつけると月イチにまとめないといけない感じになるので、そのルールは止めることにしました。

3.4.1 は syslog のビルドができない不具合 (↓のチケットを参照) でスキップしていましたが、3.4.2 では解消したので、とりあえずパッケージまでつくってみました。

bugs.ruby-lang.org

3.2.2 からの差分について、自分が修正した箇所を簡単に説明します。

cygwin.com

multiarch を適用しない

--- origsrc/ruby-3.4.2/tool/rbinstall.rb 2025-02-15 12:52:43.987135100 +0900
+++ src/ruby-3.4.2/tool/rbinstall.rb  2025-02-17 22:19:56.974920700 +0900
@@ -366,7 +366,7 @@ rubyw_install_name = CONFIG["rubyw_insta
 goruby_install_name = "go" + ruby_install_name
 
 bindir = CONFIG["bindir", true]
-if CONFIG["libdirname"] == "archlibdir"
+if CONFIG["libdirname"] == "archlibdir" && CONFIG["config_target"] != "x86_64-pc-cygwin"
   archbindir = bindir.sub(%r[/\K(?=[^/]+\z)]) {CONFIG["config_target"] + "/"}
 end
 libdir = CONFIG[CONFIG.fetch("libdirname", "libdir"), true]

multiarch に対応するための修正がマージされました。

github.com

これにより exe と dll を /usr/x86_64-pc-cygwin 配下にインストールして /usr/bin から symlink するようになるのですが、そうなると cygwin では cygruby*.dll が読めなくなって ruby.exe が起動しないような挙動になってしまいました。

ちなみに他のプラットフォームでも支障が出ていたようです。

bugs.ruby-lang.org

このデバッグをしている時に configure--disable-multiarch オプションを指定しても効かないという事象を見つけたのですが、バグなのか意図したものなのかよくわかりません。

対応としては汚いですが、cygwin の場合は archbindir を無視して、通常通り /usr/bin にインストールさせるようにしました。

pthread_attr_t の初期化

--- origsrc/ruby-3.4.2/thread_pthread.c  2025-02-15 06:25:54.000000000 +0900
+++ src/ruby-3.4.2/thread_pthread.c   2025-02-25 09:18:08.593256300 +0900
@@ -1827,7 +1827,7 @@ get_stack(void **addr, size_t *size)
 #define CHECK_ERR(expr)                \
     {int err = (expr); if (err) return err;}
 #ifdef HAVE_PTHREAD_GETATTR_NP /* Linux */
-    pthread_attr_t attr;
+    pthread_attr_t attr = {0};
     size_t guard = 0;
     STACK_GROW_DIR_DETECTION;
     CHECK_ERR(pthread_getattr_np(pthread_self(), &attr));

pthread_getattr_np 関数を呼び出して attr に自スレッドの属性情報を出力する処理で、通常は attr は未初期化でも問題ないはずなのですが、何故か cygwin ではセグることがあります。

その理由は attr の中身 (厳密に言うと pthread 情報に紐づいた cygwin DLL 内部のデータ) が初期化されているかのチェックをしているためで、0 (NULL) ではない値が入っていると、有効なアドレスだと解釈して、初期化されているかチェックする (具体的には構造体のマジックナンバー領域に pthread_*_t を表現するビットパターンが入っているか?) ことでアドレスによってはセグるという流れです。

github.com

セグること自体は去年からわかっていたのですが、gdbcygwin-exception 設定を on にしないとどこで発生しているかまったくわからないというのを教えてもらって、ようやく特定できた感じです。*1

cygwin.com

You might get more useful backtrace information after the exception with the gdb setting 'set cygwin-exceptions on' (See [1]).

[1] https://cygwin.com/faq.html#faq.programming.debugging-cygwin

この patch を適用したら、今度は別の場所でセグって、しかも cygwin-exception 設定を on にしてもやっぱりわからないままという状況なので、これについては次の回で書きます。

*1:マニュアルを読めの一言で片付くことだった...。