[pgsql-jp: 38514] Re: pgpoolがささり、子プロセスがゾンビになる現象が発生

Tatsuo Ishii ishii @ sraoss.co.jp
2007年 6月 20日 (水) 07:45:27 JST


石井です.

引用されている記事にもありますが,そのときはシグナルハンドラの中で
fork()することが本当に駄目なのかどうか分かりませんでした.ここに確信が
持てないので,いまだ修正していません.
--
Tatsuo Ishii
SRA OSS, Inc. Japan

> 高尾です。
> 
> pgpool-3.1.2をDebian GNU/Linux sargeで使用しています。
> ある程度pgpoolを動かし続けていると、pgpoolのプロセスがささり、未接続の
> pgpoolの子プロセスがゾンビ状態になる現象が発生しています。3日で発生す
> ることもあれば、1ヶ月なこともあり、とりあえず、1日1回pgpoolを再起動さ
> せるようにして、その場をしのいでいます。
> 
> それで、pgpoolがささったときにgdbでアタッチしてバックトレースを確認しました。
> それが以下です。
> 
> ----- ここから -----
> Using host libthread_db library "/lib/tls/libthread_db.so.1".
> `system-supplied DSO at 0xffffe000' has disappeared; keeping its symbols.
> 0x4014a321 in pthread_setcanceltype () from /lib/tls/libc.so.6
> #0  0x4014a321 in pthread_setcanceltype () from /lib/tls/libc.so.6
> #1  0x4010fc82 in fork () from /lib/tls/libc.so.6
> #2  0x0804a1ce in fork_a_child (unix_fd=-4, inet_fd=-4) at main.c:515
> #3  0x0804ad78 in reap_handler (sig=17) at main.c:989
> #4  <signal handler called>
> #5  0x400d8bd6 in mallopt () from /lib/tls/libc.so.6
> #6  0x400d7c43 in malloc () from /lib/tls/libc.so.6
> #7  0x400c710f in fgets () from /lib/tls/libc.so.6
> #8  0x400c71cf in fopen () from /lib/tls/libc.so.6
> #9  0x401a4d25 in _nss_files_gethostbyaddr_r () from /lib/tls/libnss_files.so.2
> #10 0x401a4297 in _nss_files_gethostbyname_r () from /lib/tls/libnss_files.so.2
> #11 0x4015119f in gethostbyname_r () from /lib/tls/libc.so.6
> #12 0x40150a96 in gethostbyname () from /lib/tls/libc.so.6
> #13 0x080567ca in connect_inet_domain_socket (secondary_backend=1)
>     at pool_connection_pool.c:340
> #14 0x0804c3ac in health_check () at child.c:1100
> #15 0x080499eb in main (argc=2, argv=0xbfffef64) at main.c:313
> ----- ここまで -----
> 
> 上記を元に、シグナルハンドラの中で、forkしている可能性があると思い、ソー
> スコードを確認しました。すると、main.cにSIGCHLDのシグナルハンドラで
> forkしていることが分かりました。
> 
> ----- ここから -----
> ...
>     pool_signal(SIGCHLD, reap_handler);
> ...
> static RETSIGTYPE reap_handler(int sig)
> {
> ...
>     /* if found, fork a new child */
>     if (!switching && !exiting && status)
>     {
>         pids[i] = fork_a_child(unix_fd, inet_fd);
>         pool_debug("fork a new child pid %d", pids[i]);
>         break;
>     }
> ...
> }
> ----- ここまで -----
> 
> 今回、私の環境で発生したpgpoolがささり、子プロセスがゾンビになる現象は、
> シグナルハンドラ中でforkしていることが原因ではないかと想像しています。
> 
> 過去のMLでは、次のようなものがありました。
> 
> ----- ここから -----
> Subject: [pgsql-jp: 35382] Re: 太る pgpool
> 2005年 5月 14日 (土) 09:17:56 JST
> http://ml.postgresql.jp/pipermail/pgsql-jp/2005-May/018942.html
> 
> > main -> reap_handler -> fork_a_child -> fork -> __i686.get_pc_thunk という
> > 経路で来て、そこで固まっているようです。
> > 
> > fork() を signal handler の中から呼んでますが、これがまずいということは
> > ないでしょうか。
> 
> 「signal handlerの中ではなるべく余計なことをするな」ということは教訓と
> して良く言われるのですが,fork()がタブーなのかはよくわかりません.もう
> ちょっと調べてみようと思いますが...
> 
> > そして、子 pgpool の看取りは waitpid(WNOHANG) でやっていますし、
> > 子の再起動のための fork_a_child(reap_handler)を signal handler から
> > 呼ぶのではなく、main() のメインループの中から定期的にキックするようにする、
> > というアイディアもあると思うんですがいかがでしょう?
> 
> とりあえずこちらの方向で検討します.heal checkを動かしているときに,起
> 動するタイミングを探すのがちょっと微妙ではありますが.
> ----- ここまで -----
> 
> 上記はかなり前の話しなので、修正されているのかなと思っていましたが、
> ソースコードを確認したところ、現在も同様の状態だと考えています。
> 「main() のメインループの中から定期的にキックするようにする」というの
> は、どうなのでしょうか。何か難しい点や、問題などがあったのでしょうか。
> 
> ---
> 株式会社ネットワーク応用通信研究所 研究員 高尾 宏治
> 〒690-0826 島根県松江市学園南二丁目12番5号
>            HOYOパークサイドビル・2F
> TEL:0852-28-9280 FAX:0852-28-9281
> URL:http://www.netlab.jp/
> e-mail:kouji @ netlab.jp
Q



pgsql-jp メーリングリストの案内