メインページに戻る
Japan Blog

デベロッパー

Google が公開しているソフトウェアの解説 ( その2 )



このエントリは、Google が Google Code でオープンソースとして公開しているソフトウェアの解説シリーズの第2回です。
今回は、Google CoreDumper というソフトウェアを紹介します。

このソフトウェアはアプリケーションプログラムから任意のタイミングでコアダンプを出力する機能を提供するライブラリです。

「 コアダンプ 」 はプロセスのある時点での状態を保存したファイルで、デバッグのときなどに利用されます。通常、プログラムが異常終了したときや特定のシグナルを受信したときに OS カーネルがコアダンプファイルを出力し、そのプロセスは終了します。開発者はそのダンプファイルを gdb などのデバッガなどで解析して問題の原因を調査します。

問題が発生してコアダンプが生成される場合以外にも動作中のプロセスのスナップショットをコアダンプファイルとして生成できれば、その時点でのプロセスの状態をあとから調査することができます。

そのような場合に使えるのがこの Google CoreDumper です。

利用方法は簡単で、まず C や C++ プログラムで CoreDumper のヘッダファイルをインクルードしておきます。


#include "google/coredumper.h"


あとはプログラム中の任意の場所で API を呼び出すだけです。


WriteCoreDump("hogehoge.core");


上のように WriteCoreDump() を呼び出せばその時点のコアダンプを作ることができます。そして、その後プロセスの実行は継続します。

ライブラリ API の詳細については、プロジェクトの Wiki ページも参照してみてください。

このライブラリの特徴は、マルチスレッドプロセスのあるスレッドから WriteCoreDump() API を呼び出したときでも、その時点のプロセス全体 ( 全スレッド ) の状態をコアダンプできることです。

コアダンプファイルを gdb に与えると各スレッドの状態が調査できます。以下にマルチスレッドプロセスのコアダンプを gdb に渡したときのサンプルを示します。


% gdb a.out hogehoge.core
GNU gdb 6.4-debian
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".

Core was generated by `./a.out'.

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /usr/local/lib/libcoredumper.so.0...done.
Loaded symbols for /usr/local/lib/libcoredumper.so.0
Reading symbols from /lib/tls/i686/cmov/libpthread.so.0...Reading symbols from /usr/lib/debug/lib/tls/i686/cmov/libpthread-2.3.6.so...done.
done.
Loaded symbols for /lib/tls/i686/cmov/libpthread.so.0
Reading symbols from /lib/tls/i686/cmov/libc.so.6...Reading symbols from /usr/lib/debug/lib/tls/i686/cmov/libc-2.3.6.so...done.
done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.3.6.so...done.
done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x0804849a in tarai ()
(gdb) info threads
11 process 12814 WriteCoreDump (file_name=0x80486dc "hogehoge.core")
at src/coredumper.c:174
10 process 12815 0x08048498 in tarai ()
9 process 12816 0x0804849d in tarai ()
8 process 12817 0x08048501 in tarai ()
7 process 12818 0x080484a0 in tarai ()
6 process 12819 0x08048498 in tarai ()
5 process 12820 0x080484a6 in tarai ()
4 process 12821 0x080484c1 in tarai ()
3 process 12822 0x0804849d in tarai ()
2 process 12823 0x080484c1 in tarai ()
* 1 process 12824 0x0804849a in tarai ()
(gdb) thread 10
[Switching to thread 10 (process 12815)]#0 0x08048498 in tarai ()
(gdb) bt
#0 0x08048498 in tarai ()
#1 0x080484ef in tarai ()
#2 0x080484ef in tarai ()
#3 0x080484be in tarai ()
#4 0x080484ef in tarai ()
#5 0x080484ef in tarai ()
#6 0x080484be in tarai ()
#7 0x080484ef in tarai ()
#8 0x080484ef in tarai ()
#9 0x080484d7 in tarai ()
#10 0x080484be in tarai ()
(中略)
#43 0x080484ef in tarai ()
#44 0x0804852d in thread_worker ()
#45 0x4e1df341 in start_thread () from /lib/tls/i686/cmov/libpthread.so.0
#46 0x4e1334ee in clone () from /lib/tls/i686/cmov/libc.so.6
(gdb)


マルチスレッドプロセスでは各スレッドの状態が非同期的に変わっていくため、ちょっと込み入ったことをする場合、頭の中で各スレッドがどのような状態になっているか想像するのがシングルスレッドの場合に比べて格段に難しくなります。ある時点での他スレッドの状態を調べたい場合などに Google CoreDumper は非常に強力な手段となるでしょう。

ただし、このライブラリは内部で ptrace システムコールを利用する関係上、動作中のプログラムは gdb や strace コマンドとの相性が悪いことに注意する必要があります。

同様のことを実現できるプログラムに、gdb の gcore コマンドがあります。しかし、プログラムのある地点でコアダンプを行うためにはブレークポイントなどを設定した上でコアダンプさせる必要があり、手順がやや煩雑になります。逆に、gcore コマンドでは適当なタイミングで非同期にコアダンプを生成させることができるので、Google CoreDumper とは目的に応じて使い分けることができるでしょう。

元々このライブラリが作られた背景には、NPTL ( Native Posix Thread Library ) が登場する前の LinuxThreads ライブラリで全スレッドの状態が入ったコアダンプファイルが作れなかったことがあったようです。当時はシグナルを受けたスレッドだけのコアダンプが生成されていました。最近の Linux カーネルは NPTL サポートによってマルチスレッドのプロセスがシグナルが送られた場合でも正しくプロセス全体のコアダンプを出力することができるようになったため、当初の目的のためのこのライブラリ必要性は薄れてきています。しかし、上に挙げたようにプログラム中の任意の箇所で同期的にコアダンプを生成できることは、特にデバッグが難しいマルチスレッドプロセスの挙動を調べるときに重宝するでしょう。

このライブラリは、非常に低レベルな技術を用いて各スレッドの状態をファイルに書き込むため、CPU アーキテクチャや OS に強く依存します。Linux 以外の OS や現在サポートされている i386 、x86_64、 ARM 以外のアーキテクチャで利用したい場合は移植が必要です。

さらに、プログラムの動作中に生成したコアダンプをチェックポイントとして、そこから再実行することに挑戦してみるのも面白いでしょう。ファイルディスクリプタやソケットといったコアダンプに含まれない情報はたくさんあるので一筋縄ではいきませんが、条件付きでも可能になれば様々な応用が考えられると思います。