Cybozu Tech Conference 2016 バグの調べ方

293 views

Published on

https://cybozutech2016.qloba.com/

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
293
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
0
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Cybozu Tech Conference 2016 バグの調べ方

  1. 1. バグの調べ方 Cybozu Tech Conrefence 2016 12/13 サイボウズ・ラボ 光成滋生
  2. 2. • 自己紹介 • 自分が開発してるもの • サイボウズ・ラボユース紹介 • 不具合調査 • サイボウズOfficeでの不具合 • Garoonでの不具合 • WalBでの不具合 • まとめ 概要 2 / 29
  3. 3. 自己紹介
  4. 4. • サイボウズの研究開発部門 • 次世代の製品・サービスの基盤となる技術を 中長期視点で研究開発する • 私 • 主にセキュリティ関係に関わる • https://github.com/herumi/ • サブでcybozu.comのバックアップレプリケーションシステム • + たまにやってくる不具合調査 サイボウズ・ラボ 4 / 29
  5. 5. • https://github.com/herumi/mcl • 汎用楕円曲線・ペアリング暗号ライブラリ • https://github.com/herumi/ate-pairing • 世界最速実装の一つ(IEEE Trans. on Computers, 2015) • 何に使うの? • 『クラウドを支えるこれからの暗号技術』 をご覧ください • 例:完全匿名可能な分散型暗号通貨 Zcashのゼロ知識証明プロトコル ペアリング暗号の実装 5 / 29
  6. 6. • 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
  7. 7. • http://labs.cybozu.co.jp/youth/requirements.html • 学生が作りたいものをサポートする • サイボウズ・ラボ社員がメンター • 比較的長期(最大1年) • 開発物はオープンソース • 給料がもらえる • 私がメンター担当したもの(一部) • 正規表現JITエンジン開発 • JavaScriptエンジン開発 • ペアリング暗号ライブラリ開発 • Intel DPDKを用いたネットワークライブラリ開発 サイボウズ・ラボユース 7 / 29
  8. 8. サイボウズOfficeでの不具合調査
  9. 9. • サイボウズOffice:中小企業向けグループウェア • ファイルキャッシュの不具合(2012年の話) • 1000秒おきにファイルキャッシュがクリア 突然サイボウズOfficeが遅くなる Office ext3 mdadm LVM kernel/driver disk ファイルシステム ソフトウェアRAID パーティション管理 メモリにキャッシュ 誰かにクリア されて遅くなる 9 / 29
  10. 10. • 手元の環境で再現させる • 結構つらい • 仕掛ける • 普通ユーザランドでキャッシュを明示的に破棄しない • 犯人はだれだ • ページキャッシュに関係するkernelの関数をwatch • flush_disk, invalidate_disk, invalidate_partition, ... • ftrace • 低負荷で手軽に使えるkernelトレーサ 再現させる&仕掛ける 10 / 29
  11. 11. • 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
  12. 12. • 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
  13. 13. • 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
  14. 14. • 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
  15. 15. • 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
  16. 16. Garoonでの不具合調査
  17. 17. • 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
  18. 18. • Address sanitizerで調査 • エラーで落ちるがそのメモリがどう壊れてるのか、 どこで確保されたのかはわからない • 自前ツールで調査 • 全てのmalloc/freeを記録して整合性をチェック • 共有ライブラリを通してかなり複雑なやりとりをしている • ひとまず解決 • このバージョンのPHPではopcache.fast_shutdown=0だと エラーになるパスを通らないことを確認 • パフォーマンス劣化も許容範囲内 • 同時に軽微なメモリ破壊の修正patch メモリチェックツール 18 / 29
  19. 19. WalBでの不具合調査その1
  20. 20. • WalB • cybozu.comの次期バックアップレプリケーションシステム • ブロックデバイスの全IOを記録する • デーモン・制御ツールはC++/Python • ラボ:星野(メイン) + 私(サブ) • 現在、星野とSRE(インフラ)チームで本運用に向け最終開発 WalBでおかしな実行バイナリ WalB storage アプリケーション Diff backup storage replicated storage 20 / 29
  21. 21. • 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
  22. 22. • 3万行のコードからひたすらコードを削る • 少し変更するだけで動いたり、動かなかったりで難しい • 最終的に30行ほどで落ちるコード • 結局gdbのシンボルパーサにバグ • template+継承+ラムダ式のコンボによる複雑なシンボル • 当時のcurrent版で修正済みだった おもしろい 22 / 29
  23. 23. WalBでの不具合調査その2
  24. 24. • 試験運用時書き込みデータ(logpack)に不正を検出 • しばらくretryしてシステムは継続 • 一度しか発生せず致命的ではなかったため様子見 • しかし20日後再現 • 対応作業 • コードレビュー • チェックコード • 3週間に一度しか起こらないのでよくわからない WalBで不正なlogを検出 24 / 29
  25. 25. • エラーの再現頻度を上げるチェッカーツールの作成 • 最短で10分に一度エラーが発生! • 条件によって数時間走らせても出ないことも • WalB driverのflushまわりの制御バグを発見 • ツールを1日走らせてもエラーが出なくなった • 問題解決か? • 残念 • ツールを使っても3日に一度エラーが発生 原因究明作業(主に星野担当) 25 / 29
  26. 26. • diskの読み書きは非同期 • データは分割・統合されうる • 実際にはflush処理もある 原因追求が難しい理由 write() user空間 WalB driver/kernel空間 logの書き込みsubmit disk 書き込み complete完了 dataのコピー・統合・分割 dataの書き込みsubmit 書き込み complete 26 / 29
  27. 27. • いろいろ調べても悪そうには見えない • 環境によって出るのと出ないのと • 同じマシンでも出やすかったりそうでなかったり • 何が違うのかなかなか思い当たらない • つらい期間 • WalBのせいじゃないのではないかという仮定の元に 複数書き込みを模倣するユーザランドツールを作成 • 同じエラーが発生 • WalB driverのせいではなかった! • では犯人はdisk driver or kernel? WalB driverのせいなのか? 27 / 29
  28. 28. • 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
  29. 29. • まずは自分たちのコードを疑う • ほとんどは自分のミス • 論理的に、ときにはひらめきで追いかける • ありそうにないものが犯人のときもある • つらいときでも耐える • 気分転換でもして バグの調べ方のまとめ 29 / 29

×