29
バグの調べ方 Cybozu Tech Conrefence 2016 12/13 サイボウズ・ラボ 光成滋生

Cybozu Tech Conference 2016 バグの調べ方

Embed Size (px)

Citation preview

Page 1: Cybozu Tech Conference 2016 バグの調べ方

バグの調べ方

Cybozu Tech Conrefence 2016

12/13

サイボウズ・ラボ 光成滋生

Page 2: Cybozu Tech Conference 2016 バグの調べ方

• 自己紹介

• 自分が開発してるもの

• サイボウズ・ラボユース紹介

• 不具合調査

• サイボウズOfficeでの不具合

• Garoonでの不具合

• WalBでの不具合

• まとめ

概要

2 / 29

Page 3: Cybozu Tech Conference 2016 バグの調べ方

自己紹介

Page 4: Cybozu Tech Conference 2016 バグの調べ方

• サイボウズの研究開発部門

• 次世代の製品・サービスの基盤となる技術を

中長期視点で研究開発する

• 私

• 主にセキュリティ関係に関わる

• https://github.com/herumi/

• サブでcybozu.comのバックアップレプリケーションシステム

• + たまにやってくる不具合調査

サイボウズ・ラボ

4 / 29

Page 5: Cybozu Tech Conference 2016 バグの調べ方

• https://github.com/herumi/mcl

• 汎用楕円曲線・ペアリング暗号ライブラリ

• https://github.com/herumi/ate-pairing

• 世界最速実装の一つ(IEEE Trans. on Computers, 2015)

• 何に使うの?

• 『クラウドを支えるこれからの暗号技術』

をご覧ください

• 例:完全匿名可能な分散型暗号通貨

Zcashのゼロ知識証明プロトコル

ペアリング暗号の実装

5 / 29

Page 6: Cybozu Tech Conference 2016 バグの調べ方

• https://github.com/herumi/xbyak

• 暗号ライブラリなどのために開発

• 来年やその後に出る予定のCPUのAVX-512に対応

• gcc-6, clang-4, NASM, VC2015, Intel SDEなどのツールは

AVX512_4FMAPS, AVX512_4VNNIWに未対応(2016/11)

• Intelの機械学習ライブラリCaffeやMKL-DNNで利用される

C++用JITアセンブラXbyak

実装したけど正しく動いてるかツールが無いので分からん

未公開のIntelソフトウェアXEDで確認したよ

6 / 29

Page 7: Cybozu Tech Conference 2016 バグの調べ方

• http://labs.cybozu.co.jp/youth/requirements.html

• 学生が作りたいものをサポートする

• サイボウズ・ラボ社員がメンター

• 比較的長期(最大1年)

• 開発物はオープンソース

• 給料がもらえる

• 私がメンター担当したもの(一部)

• 正規表現JITエンジン開発

• JavaScriptエンジン開発

• ペアリング暗号ライブラリ開発

• Intel DPDKを用いたネットワークライブラリ開発

サイボウズ・ラボユース

7 / 29

Page 8: Cybozu Tech Conference 2016 バグの調べ方

サイボウズOfficeでの不具合調査

Page 9: Cybozu Tech Conference 2016 バグの調べ方

• サイボウズOffice:中小企業向けグループウェア

• ファイルキャッシュの不具合(2012年の話)

• 1000秒おきにファイルキャッシュがクリア

突然サイボウズOfficeが遅くなる

Office

ext3

mdadm

LVM

kernel/driver

disk

ファイルシステム

ソフトウェアRAID

パーティション管理

メモリにキャッシュ

誰かにクリア されて遅くなる

9 / 29

Page 10: Cybozu Tech Conference 2016 バグの調べ方

• 手元の環境で再現させる

• 結構つらい

• 仕掛ける

• 普通ユーザランドでキャッシュを明示的に破棄しない

• 犯人はだれだ

• ページキャッシュに関係するkernelの関数をwatch

• flush_disk, invalidate_disk, invalidate_partition, ...

• ftrace

• 低負荷で手軽に使えるkernelトレーサ

再現させる&仕掛ける

10 / 29

Page 11: Cybozu Tech Conference 2016 バグの調べ方

• invalidate_partitionが呼ばれた

• 呼び出したのはmdadm

• 犯人はこいつか

• gdbでattach

ヒット

mdadm-900 [001] .... 75491.384221: __invalidate_device <-invalidate_partition => ftrace_call => invalidate_partition => rescan_partitions => __blkdev_get => blkdev_get ... => do_sys_open => sys_open

gdb -p 9000 gdb) bt #0 0x00007f85b1ebf103 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:82 #1 0x000000000040de66 in mdstat_wait (seconds=1000) at mdstat.c:317 #2 0x000000000042dea1 in Monitor (devlist=0x0, mailaddr=0x1a7b020 "root",

waitしてる時間が1000秒

11 / 29

Page 12: Cybozu Tech Conference 2016 バグの調べ方

• mdのモニタツールがinvalid_partitionを呼んでいる

• 呼ぶとはとても思えないが...

• /dev/mdをオープンするだけでクリアされると判明

• mdのドライバが犯人か?

位置関係(1/3)

mdデーモン

md driver

disk driver

disk

invalid_partition()

キャッシュクリア

モニタツール

fd = open("dev/md/test..", O_RDONLY);

kernel

user

12 / 29

Page 13: Cybozu Tech Conference 2016 バグの調べ方

• md_open()がinvalid_partitionを呼ぶとは思えない...

• 調べたがmd_openは悪くはなかった

• スタックトレースの途中にあったblkdev_get()を見てみる

位置関係(2/3)

mdデーモン

md driver

disk driver

disk

invalid_partition()

キャッシュクリア

モニタツールopen()

md_open()

kernel

user

13 / 29

Page 14: Cybozu Tech Conference 2016 バグの調べ方

• bd_invalidatedが怪しい

blkdev_get

__blkdev_get(...) { ... ret = disk->fops->open(bdev, mode); ... if (bdev->bd_invalidated) { if (!ret) rescan_partitions(disk, bdev); else if (ret == -ENOMEDIUM) invalidate_partitions(disk, bdev);

md_openが呼ばれる

__invalidate_partitionが呼ばれる

14 / 29

Page 15: Cybozu Tech Conference 2016 バグの調べ方

• mdは悪くなかった

• kernel/fsのバグ

• check_disk_size_change()内でbd_invalidatedをクリアし忘れ

• kernel patchを送る

位置関係(3/3)

mdデーモン

md driver

disk driver

disk

bd_invalidatedがtrueなら invalid_partition()

モニタツールopen()

blk_dev() kernel

user

md_open() // 引っかけ

キャッシュクリア

15 / 29

Page 16: Cybozu Tech Conference 2016 バグの調べ方

Garoonでの不具合調査

Page 17: Cybozu Tech Conference 2016 バグの調べ方

• Garoon:中堅・大規模組織向けグループウェア

• リリース予定の少し前に不具合が発覚(2015年の話)

• PHPのheapが壊れて死んだ

• 本社チームがさまざまな設定で検証

• OPcacheを無効にすると発生しない

• OPcache : PHPのコンパイル結果をキャッシュして高速化

• パフォーマンス劣化は許容範囲外

• opcache.max_accelerated_filesを増やすと発生しない

• Garoonのファイルは約7000個

• ファイルキャッシュを越えると不具合か?

突然Garoonが白くなる

[.10:59:22] WARNING: [pool www] child 19055 said into stderr: "zend_mm_heap corrupted" [.10:59:22] WARNING: [pool www] child 19055 exited with code 1 after 946.944662 seconds from start

17 / 29

Page 18: Cybozu Tech Conference 2016 バグの調べ方

• Address sanitizerで調査

• エラーで落ちるがそのメモリがどう壊れてるのか、

どこで確保されたのかはわからない

• 自前ツールで調査

• 全てのmalloc/freeを記録して整合性をチェック

• 共有ライブラリを通してかなり複雑なやりとりをしている

• ひとまず解決

• このバージョンのPHPではopcache.fast_shutdown=0だと

エラーになるパスを通らないことを確認

• パフォーマンス劣化も許容範囲内

• 同時に軽微なメモリ破壊の修正patch

メモリチェックツール

18 / 29

Page 19: Cybozu Tech Conference 2016 バグの調べ方

WalBでの不具合調査その1

Page 20: Cybozu Tech Conference 2016 バグの調べ方

• WalB

• cybozu.comの次期バックアップレプリケーションシステム

• ブロックデバイスの全IOを記録する

• デーモン・制御ツールはC++/Python

• ラボ:星野(メイン) + 私(サブ)

• 現在、星野とSRE(インフラ)チームで本運用に向け最終開発

WalBでおかしな実行バイナリ

WalB

storage

アプリケーション

Diff

backup

storage

replicated

storage

20 / 29

Page 21: Cybozu Tech Conference 2016 バグの調べ方

• gdbでデバッグしようとしたらgdbが落ちる

• 起動も何もしていない

• gdbを使わなければプログラム自体は普通に動く

• 1行だけデータをコメントアウトしたらgdbでも動いた

ある日のデバッグ

gdb --args binsrc/archive-server -vg vg1 -p 10201 -b /home/shigeo/Program/walb-tools/stest/tmp/a1 -l /home/shigeo/Program/walb-tools/stest/tmp/a1.log -id a1 -debug GNU gdb (Ubuntu 7.7-0ubuntu3.1) 7.7 ...(snip) Type "apropos word" to search for commands related to "word"... Reading symbols from binsrc/archive-server...Segmentation fault (core dumped)

const protocol::Str2ServerHandler archiveHandlerMap = { ... // { dirtyFullSyncPN, s2aDirtyFullSyncServer }, /* 動く・動かないの分岐点 */ };

21 / 29

Page 22: Cybozu Tech Conference 2016 バグの調べ方

• 3万行のコードからひたすらコードを削る

• 少し変更するだけで動いたり、動かなかったりで難しい

• 最終的に30行ほどで落ちるコード

• 結局gdbのシンボルパーサにバグ

• template+継承+ラムダ式のコンボによる複雑なシンボル

• 当時のcurrent版で修正済みだった

おもしろい

22 / 29

Page 23: Cybozu Tech Conference 2016 バグの調べ方

WalBでの不具合調査その2

Page 24: Cybozu Tech Conference 2016 バグの調べ方

• 試験運用時書き込みデータ(logpack)に不正を検出

• しばらくretryしてシステムは継続

• 一度しか発生せず致命的ではなかったため様子見

• しかし20日後再現

• 対応作業

• コードレビュー

• チェックコード

• 3週間に一度しか起こらないのでよくわからない

WalBで不正なlogを検出

24 / 29

Page 25: Cybozu Tech Conference 2016 バグの調べ方

• エラーの再現頻度を上げるチェッカーツールの作成

• 最短で10分に一度エラーが発生!

• 条件によって数時間走らせても出ないことも

• WalB driverのflushまわりの制御バグを発見

• ツールを1日走らせてもエラーが出なくなった

• 問題解決か?

• 残念

• ツールを使っても3日に一度エラーが発生

原因究明作業(主に星野担当)

25 / 29

Page 26: Cybozu Tech Conference 2016 バグの調べ方

• diskの読み書きは非同期

• データは分割・統合されうる

• 実際にはflush処理もある

原因追求が難しい理由

write()

user空間 WalB driver/kernel空間

logの書き込みsubmit

disk

書き込み

complete 完了

dataのコピー・統合・分割

dataの書き込みsubmit 書き込み

complete

26 / 29

Page 27: Cybozu Tech Conference 2016 バグの調べ方

• いろいろ調べても悪そうには見えない

• 環境によって出るのと出ないのと

• 同じマシンでも出やすかったりそうでなかったり

• 何が違うのかなかなか思い当たらない

• つらい期間

• WalBのせいじゃないのではないかという仮定の元に

複数書き込みを模倣するユーザランドツールを作成

• 同じエラーが発生

• WalB driverのせいではなかった!

• では犯人はdisk driver or kernel?

WalB driverのせいなのか?

27 / 29

Page 28: Cybozu Tech Conference 2016 バグの調べ方

• disk IOを詳細に取得できるツール

• completedでdiskの書き込みは完了しているはずなのに

3296001番目のセクタの中身はは0のままだった

• RAIDカードのドライバかファームウェアの不具合

blktrace

252,7 1 12079 228.808092957 4494 Q W 3296001 + 1 [kworker/u66:21] 8,2 1 162836 228.808094689 4494 A W 622367489 + 1 <- (252,7) 3296001 8,0 1 162837 228.808095153 4494 A W 622867201 + 1 <- (8,2) 622367489 8,0 1 162838 228.808095648 4494 Q W 622867201 + 1 [kworker/u66:21] 8,0 1 162839 228.808099628 4494 G W 622867201 + 1 [kworker/u66:21] 252,7 1 12080 228.808101183 4494 Q W 3296002 + 256 [kworker/u66:21] 8,2 1 162840 228.808101724 4494 A W 622367490 + 256 <- (252,7) 3296002 ... (snip) ... 8,0 1 162854 228.808198793 4494 Q W 622867459 + 256 [kworker/u66:21] 8,0 1 162855 228.808199268 4494 G W 622867459 + 256 [kworker/u66:21] 8,0 7 187897 228.808255052 4367 C W 622867202 + 256 [0] 252,7 7 19389 228.808256993 4367 C W 3296002 + 256 [0] 8,0 7 187898 228.808260877 4367 C W 622867201 + 1 [0] 252,7 7 19390 228.808261198 4367 C W 3296001 + 1 [0]

heder submitted

logpack submitted

logpack completed

header completed

28 / 29

Page 29: Cybozu Tech Conference 2016 バグの調べ方

• まずは自分たちのコードを疑う

• ほとんどは自分のミス

• 論理的に、ときにはひらめきで追いかける

• ありそうにないものが犯人のときもある

• つらいときでも耐える

• 気分転換でもして

バグの調べ方のまとめ

29 / 29