5 ポイント 投稿者 GN⁺ 2025-01-24 | 4件のコメント | WhatsAppで共有
  • ARM64でのみ発生したクラッシュ

    • EdgeDBのネットワークI/OコードをPythonからRustへ移植する過程で、ARM64のCIランナーでテストが断続的に失敗する問題が発生した。
    • 当初はデッドロックのように見えたが、実際にはプロセスがクラッシュしており、テストランナーがそれを検知できていなかった。
  • 初期の仮説

    • ARM64でのみ問題が発生する理由を理解するため、メモリモデルの違いを考慮した。
    • Intelのメモリモデルは厳格である一方、ARMはより弱いメモリモデルを持つ。
  • CIマシンでのデバッグ

    • AWSでARM64ランナーに直接接続して問題を調査した。
    • プロセスがクラッシュしてコアダンプを残しており、それを調べることで問題の原因を突き止めた。
  • 実際の原因: setenvとgetenv

    • setenvはマルチスレッド環境で安全ではなく、getenvとの相互作用でクラッシュを引き起こす可能性がある。
    • 環境変数の再割り当てが問題の原因であることが判明した。
  • openssl_probeとの関連

    • openssl-probeSSL_CERT_FILESSL_CERT_DIR環境変数を設定する際に問題が発生した。
    • Rustのrust-native-tlsがこれらの環境変数を設定する過程でクラッシュが発生した。
  • ARM64 Linuxでのみ発生した理由

    • クラッシュは複数の条件が重なった場合にのみ発生し、環境変数の数やI/O失敗などがその条件に含まれる。
  • 解決策

    • reqwestrust-native-tls/opensslバックエンドからrustlsへ移行することを決定した。
    • Rustプロジェクトは環境設定関数をunsafeにする計画であり、glibcプロジェクトはgetenvのスレッド安全性を改善している。

4件のコメント

 
carnoxen 2025-01-24

Setenv はスレッドセーフではなく、C はこれを修正したくない

setenv 関数がまた問題を起こしています。

 
y15un 2025-01-24

私はタイトルを「C stdlibのスレッド非安全性は、安全だとされるRustでさえ救えない」と書くつもりです。 :)

 
halfenif 2025-01-24

確かに理解しました。

 
GN⁺ 2025-01-24
Hacker Newsの意見
  • Rustの次のエディションでは環境設定関数がunsafeになる予定で、競合するcrateに影響する可能性がある

    • Rust標準ライブラリのset_varremove_varは、2024 editionではunsafe {}ブロックの使用が必要になる
    • 現在のドキュメントでも安全性の問題には触れられているが、そもそもこれらの関数を安全にしたこと自体が誤りだった
  • glibc向けのパッチでgetenvはより安全になったが、Cでは依然として環境へ直接アクセスできるため、完全に安全ではない

    • C標準ライブラリのメンテナーはsetenvをマルチスレッド安全にすることに消極的だが、少なくとも新しいスレッドセーフAPIは定義されるべきだ
    • Muslのメンテナーも、この問題を解決不能だと確信しているわけではない
  • Linuxで環境まわりのバグに遭遇するのは、ある種の通過儀礼のように見なされている

    • LinusとカーネルはPOSIXのバグ修正に関しては実用的だが、glibcは依然として後れを取っている
    • getenv_r()を提供し、setenv()と同期させ、コンパイル時・リンク時に警告を出すようにしていれば、問題解決の助けになったはずだ
  • 環境変数を使った設定は"12-factor app"ムーブメントの一部だったが、これは愚かなやり方だと思う

    • 環境変数の代わりにYAMLのような設定ファイルを使うほうがよい方法だと思う
  • Amazon AWS上で動くCIマシンは、実際のrootユーザーを使えるという利点がある

    • クラウドやコンテナなしでローカルでコードをビルドし、デバッグする能力を失ってしまったように思える
  • 直感に反するバグを掘り下げた素晴らしい記事だ

    • このような詳細なトラブルシューティング報告は、自分で実際にやってみるのに最も近い体験を与えてくれる
  • env::set_varは今やunsafeになった

    • シングルスレッドのプログラムでは安全に呼び出せる
    • Windowsではシングルスレッド、マルチスレッドのいずれのプログラムでも常に安全だ
    • 他のOS上のマルチスレッドプログラムでは、set_varremove_varを使わないことが唯一の安全な選択だ
  • あるコードベースでsetproctitleが動かなかった経験を思い出させる

    • numpyをインポートした後はsetproctitleが動作せず、これはnumpy初期化時のgetenvまたはsetenv呼び出しによってenvironのアドレスが変更されたためだ