2019年1月8日火曜日

[Azure Pipelines] Ubuntu 環境でコアダンプを成果物に保存するようにした

マトリックスを組んだものの、テストが 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

0 件のコメント:

コメントを投稿