計算クラスター全体で実行される C アプリケーションを作成しています (condor を使用)。問題のあるコードを明らかにするために多くの方法を試しましたが、役に立ちませんでした。
手がかり:
- 15 台のマシンで 2 日間コードを実行すると、平均して 2 つまたは 3 つのセグメンテーション違反 (シグナル 11) が発生します。
- コードをローカルで実行すると、segfault が発生しません。自宅のマシンで 3 週間近く実行しました。
試み:
- ローカルで valGrind のコードを 4 日間実行しましたが、メモリ エラーは発生しませんでした。
- プログラムの状態の一部を出力できるように、独自のシグナル ハンドラーを定義して segfault シグナルをキャプチャしました。
- これで、segfault が発生したときに、バックトレースを使用して現在のスタックを出力できます。
- 変数値を出力できます。
- 現在の行番号に設定される変数を作成しました。
- また、問題が解決すればセグメンテーション違反が見つかることを期待して、コードのチャンクをコメントアウトしようとしました。
悲しいことに、出力される行番号はかなりランダムです。スタックトレースで何ができるか完全にはわかりません。セグメンテーション違反が発生した関数のアドレスのみを記録すると仮定して正しいですか?
疑惑:
- コンドルがマシン間でジョブを移動するために使用するチェック ポインティング システムは、メモリの破損に対してより敏感であると思われます。これがローカルで見られない理由です。
- そのインデックスがバグによって破損しており、これらのインデックスがセグメンテーション違反を引き起こしていること。これは、セグメンテーション違反がかなりランダムな行番号で発生しているという事実を説明します。
アップデート
これをさらに調査すると、次のリンクが見つかりました。
LibSegFault - セグメンテーション違反に関する状態データを自動的にキャッチして出力するためのライブラリ。
segfault のキャッチに関するGCC チュートリアルを使用したスタックの巻き戻し (スタック トレース) と、問題のある命令の行番号の取得。
更新 2
Greg は、condor のログを見て、「コンドルがチェックポイントから実行可能ファイルを再起動したときにセグメンテーション違反を関連付ける」ことを提案しました。ログを見ると、segfaults はすべて再起動直後に発生します。すべての障害は、ジョブがあるタイプのマシンから別のタイプのマシンに切り替わったときに発生するようです。
更新 3
コンドル送信ファイルの「requiremets」フィールドを問題に設定することで、ホスト間の違いによって引き起こされていたセグメンテーション違反は完全になくなりました。
個々のマシンを設定できます:
requirements = machine == "hostname1" || machine == "hostname2"
またはマシンのクラス全体:
requirements = classOfMachinesName
要件の例はこちら