マトリックスを組んだものの、テストが Abort (core dump) してしまっていたので原因の解明のため、コアダンプを成果物として保存するようにした話です。
(コアダンプを出力するあたりは Azure Pipelines は全く関係なく、関係するのは成果物の保存くらいですが)
ulimit -c unlimited
まずは、デフォルトで
core file size (blocks, -c) 0
になっているので ulimit -c unlimited しておきます。
apport
環境によっては ulimit の設定だけで core ファイルが出ますが、azure pipelines の ubuntu 環境はそうではありませんでした。
apport が有効になっているため、ulimit -c unlimited だけでは core dump ファイルは出力されません。
方法としては、2つ考えられます。
* apport を使わないようにする
* apport でファイル出力されるようにする
最初は /proc/sys/kernel/core_pattern を書き換えて、apport を使わないようにする方法をやってみたのですが、設定を書き換えて再起動する必要があるようだったので apport 有効な状態でファイルが出力されるようにしました。
ファイル出力されるように設定する
まずは、ファイルが出力されるようにします。
apport は通常非パッケージプログラムのクラッシュは、ダンプをファイル出力しないようです。
つまり、CI で実行されるテストは非パッケージプログラムなので、ファイルが出力されてなかったわけですね。
ubuntu - How to change apport default behaviour for non-packaged application crashes? - Stack Overflow
~/.config/apport/settings に以下の設定を書き込みます。
mkdir -p ~/.config/apport/
echo [main] > ~/.config/apport/settings
echo unpackaged=true >> ~/.config/apport/settings
これにより、/var/crash フォルダにダンプが出力されるようになります。
Unpack
つづいて、gdb で解析可能なようにファイルを unpack します。
apport が出力クラッシュダンプファイルは、素に出力した core dump ファイルのように gdb に食わせることができないためです。
apport - How does one get a hold of the details regarding a system/application crash - Ask Ubuntu
これには apport-unpack を使えばよいのですが、以下のエラーが出てうまくいきませんでした。
Traceback (most recent call last):
File "/usr/bin/apport-unpack", line 73, in
pr.extract_keys(f, bin_keys, dir)
File "/usr/lib/python3/dist-packages/problem_report.py", line 270, in extract_keys
[item for item, element in b64_block.items() if element is False])
ValueError: ['UserGroups'] has no binary content
検索してもスマートな解決方法が見つからなかったので、 UserGroups に値を付け加えて unpack するようにして回避しました。
mkdir test/coredump
for file in `\find /var/crash/ -name '*.crash'`; do sudo sed -i -e "s/UserGroups:\s*$/UserGroups:iutest/g" $file ; done
for file in `\find /var/crash/ -name '*.crash'`; do apport-unpack $file test/coredump/`basename $file .crash` ; done
これで test/coredump フォルダにクラッシュダンプが保存されてるようになったので、あとは成果物として保存します。
成果物を保存する
ようやく Azure Pipelines の設定です。
(といってもとっても簡単なのでほとんど書くことありませんが)
- task: PublishPipelineArtifact@0
condition: failed()
inputs:
artifactName: 'core dump'
targetPath: 'test/coredump'
成果物の保存には「PublishPipelineArtifact」タスクを使います。
artifactName に成果物の名前と targetPath にダンプを出力したディレクトリを指定します。
クラッシュする=ジョブの失敗なので、 condition: failed() も指定しておきましょう。
これで成果物が保存されます。
成果物は右上の「…」メニューに「Artifacts」があるので、そこに artifactName で指定した名前がリストアップされます。
保存した成果物を開くと「Artifacts explorer」が開くのでそこから成果物をダウンロードしてくることができます。
コアダンプの解析
CoreDump ファイルをダウンロードしたら、自前の Ubuntu docker コンテナを起動して、以下のコマンドを実行。
gdb ./all_tests CoreDump
(gdb) bt
iutest::detail::IOutStream::Printf で落ちてるのがわかりました。
これをもとにちゃんと修正することができました。よかったよかった。
-DIUTEST_HAS_VARIADIC_TEMPLATES=0 failed test · Issue #131 · srz-zumix/iutest
最後に
Ubuntu でのコアダンプの出力にだいぶ手間取りましたが、よく使うものがタスク化されていて、コンディションで条件付けもしやすかったので、パイプラインの構築は簡単でした。
これで、テストがクラッシュしたときに、より調査しやすいパイプラインになったかなと思います。
Azure Pipelines さんこれからもよろしくお願いしますmm