18. valgrind で PostgreSQL のメモリリークをみつけよう - PostgreSQL のソースコードを読む
valgrind については、C(++)言語: valgrindの使い方 を参照。
準備
% sudo apt-get install valgrind % sudo apt-get install libreadline-dev libz-dev
PostgreSQL 8.3.6 のインストール。
% ./configure --prefix=/tmp/local
% make
% make check
PostgreSQL起動
% /tmp/local/bin/postgres -D /tmp/data server starting % /tmp/local/bin/createdb hige % /tmp/local/bin/psql -n hige
valgrind 経由で起動
起動する。
% valgrind --leak-check=full /tmp/local/bin/postgres -D /tmp/data
別のコンソールから停止。
/tmp/local/bin/pg_ctl -D /tmp/data -l logfile stop
leak 箇所が出ました。
==25137== 39 bytes in 1 blocks are definitely lost in loss record 3 of 12 ==25137== at 0x4C265AE: malloc (vg_replace_malloc.c:207) ==25137== by 0x556E3F1: strdup (in /lib/libc-2.8.90.so) ==25137== by 0x68F4FE: set_pglocale_pgservice (in /tmp/local/bin/postgres) ==25137== by 0x548FC9: main (in /tmp/local/bin/postgres) ==25137== ==25137== ==25137== 3,348 (264 direct, 3,084 indirect) bytes in 1 blocks are definitely lost in loss record 7 of 12 ==25137== at 0x4C265AE: malloc (vg_replace_malloc.c:207) ==25137== by 0x67F76C: save_ps_display_args (in /tmp/local/bin/postgres) ==25137== by 0x548FB9: main (in /tmp/local/bin/postgres)
あれれ。ソースコード情報が出ない。デバッグビルドしていなかったからか。
% CFLAGS=-g ./configure --prefix=/tmp/loca
で PostgreSQL ビルドし直し。
もう一度。実行。
==7201== 39 bytes in 1 blocks are definitely lost in loss record 3 of 12 ==7201== at 0x4C265AE: malloc (vg_replace_malloc.c:207) ==7201== by 0x556E3F1: strdup (in /lib/libc-2.8.90.so) ==7201== by 0x73B48F: set_pglocale_pgservice (exec.c:660) ==7201== by 0x593656: main (main.c:90) ==7201== ==7201== ==7201== 3,373 (264 direct, 3,109 indirect) bytes in 1 blocks are definitely lost in loss record 7 of 12 ==7201== at 0x4C265AE: malloc (vg_replace_malloc.c:207) ==7201== by 0x724896: save_ps_display_args (ps_status.c:162) ==7201== by 0x593641: main (main.c:79)
ソースコード情報(ファイル、行番号)が表示されるようになった。
感じをつかもう
表示されたリークがクリティカルなものかどうかはわからないが、今後の作業で似たようなことを繰り返すであろうから慣れのために調べよう。
GNU global で見ていくと exec.c:660 は以下の通り。
putenv(strdup(env_path));
ふむ。許容範囲な気もするが、putenv の仕様を見てみようか。
string が指している文字列は環境の一部となるので、 文字列を変更すると環境も変更される。
ということなのでありかな。
あとで回収できるように、どこかで参照を残しておくというまじめな方法もあるが、数が少ないのでとりあえずよしとしよう。
今後
postgresql は接続に対して fork するので1接続で大量に select 文などを投げまくってメモリリークが起きていないか調べよう。