[PHP-users 34784] Re: sleep関数が復帰せずプロセスがダウンする

Yuji KUBOTA kubota.yuji @ forestgroup.net
2009年 9月 20日 (日) 21:15:52 JST


皆様

この度はお世話になっております。久保田と申します。

PHPプログラムのプロセスがダウンする原因について、皆様より頂いたコメントおよび私
の方で再度調べた結果を以下にまとめました。
(常駐プログラムの実現方法に関しては、別途整理させて下さい)
まだ、疑問点が残っております。3項に示しましたので、コメントを頂けると助かります。

1.プロセス構成
今回の動作確認プログラムは、以下のプロセス構成で実行されていると認識しました。
主に、睦月さまからのコメントを参考にさせて頂きました。
http://ml.php.gr.jp/pipermail/php-users/2009-September/035297.html

┌─────┐
│  httpd   │
│          │
│          │
│          │
└──┬──┘
      │
      │HTTPリクエスト
     ↓
┌─────┐
│プログラム│
│    X    │プログラムX:プログラムAをバックグランドでプロセス起動
│(Worker   │するPHPプログラム
│ プロセス)│
└──┬──┘
      │
      │プロセス起動(起動後復帰)
      ↓
┌─────┐
│プログラム│
│    A    │プログラムA:10秒間sleep処理を無限に繰り返すPHPプログラム
│          │
│          │
└─────┘

なお、Workerプロセスは、Apacheの設定により最大10個のプロセスが起動しておりまし
た。以下にhttpd.confの設定内容を示します。

<IfModule prefork.c>
StartServers       5
MinSpareServers    5
MaxSpareServers   10
ServerLimit      300
MaxClients       300
</IfModule>

また、Workerプロセスの動作状況を以下に示します。

root     22377  0.0  0.4  32452 15372 ?        Ss   Sep13   0:12 /usr/sbin/httpd
apache   27070  0.0  0.3  34000 13408 ?        S    00:10   0:00  \_ /usr/sbin/httpd
apache   27073  0.0  0.3  34464 14124 ?        S    00:10   0:01  \_ /usr/sbin/httpd
apache   27074  0.0  0.3  34424 13996 ?        S    00:10   0:00  \_ /usr/sbin/httpd
apache   27327  0.0  0.3  34564 14128 ?        S    00:16   0:01  \_ /usr/sbin/httpd
apache   27333  0.0  0.3  34048 13264 ?        S    00:16   0:00  \_ /usr/sbin/httpd
apache   28883  0.0  0.3  34568 14428 ?        S    01:04   0:00  \_ /usr/sbin/httpd
apache   28885  0.0  0.3  34372 13256 ?        S    01:04   0:01  \_ /usr/sbin/httpd
apache   32552  0.0  0.3  33788 13092 ?        S    02:56   0:00  \_ /usr/sbin/httpd
apache   14492  0.0  0.3  34264 13688 ?        S    10:03   0:00  \_ /usr/sbin/httpd
apache   14493  0.0  0.3  34176 13632 ?        S    10:03   0:00  \_ /usr/sbin/httpd

2.現象(まとめのため再度掲載)
なぜか、プロセス(プログラムA)が毎回00:10にダウンする現象が発生します。
詳細は以下のページを参照下さい。
http://ml.php.gr.jp/pipermail/php-users/2009-September/035280.html
http://ml.php.gr.jp/pipermail/php-users/2009-September/035296.html

3.プロセス(プログラムA)ダウンの原因(現状の見解)
Apacheのログ・ローテーション機構により、httpdプロセス(Workerプロセスの親プロセ
ス)に対して、毎日00:02にHUPシグナルが送信されていたため、httpdプロセスの再起動
が行われていました。
その為、Workerプロセスも再起動される事で、Workerプロセス経由で起動されたプロセス
(プログラムA)がダウンすると言う見解です。
HUPシグナルを無視するようにプロセスを起動した際には、プロセスダウンが発生しない
事が判りました。
http://ml.php.gr.jp/pipermail/php-users/2009-September/035300.html
しかし、まだ納得がいかない点があります。3項に示します。

・crontabの設定内容
02 0 * * * root run-parts /etc/cron.daily

・ログ・ローテーションの設定内容
/xxx/log/*log {
    missingok
    daily
    rotate 2
    notifempty
    sharedscriptslogrotate
    postrotate
        /bin/kill -HUP `cat /var/run/httpd.pid 2>/dev/null` 2> /dev/null || true
    endscript
}

・HUPシグナルを送信する必要性
ログのローテーション後にログファイルにログを吐き出していたプロセスがログファイル
を見失ってしまうと、以降ではログが採取されなくなってしまいます。この回避策とし
て、postrotate〜endscript の間で、syslogにHUPシグナルを送り、再起動をすること
で、ローテーション後に create によって作成されたファイルに正常にsyslogがログを吐
き出すようにしているのです。

3.疑問点
Q1:UNIX系OSのプロセス管理では、親プロセスが先に死ぬと子プロセスはinitプロセス
の養子になるだけで、子プロセスも一緒に死なないと理解しております。

[参考ホームページ]
http://japan.zdnet.com/reference/solaris/story/0,3800077752,20365855,00.htm

と言う事は、今回のケースにおいて、Workerプロセスの再起動(一時的に死ぬ)によりプ
ロセス(プログラムA)はダウンする必要はないと考えます。
現象と逆の結果になってしまいます。
また、プログラムXをtelnet端末(rootアカウント)から起動しtelnet端末ログアウト後
(親プロセスが死んだ状態)もプロセス(プログラムA)はダウンする事なく動作し続け
ております。
理屈がもう一歩通らず、何かまだ理解が足りないようです。
なぜ、Workerプロセスの再起動で、子プロセスであるプロセス(プログラムA)がダウン
する必要があるのでしょうか。
HUPシグナルが伝搬される仕様(OSまたはPHP)なのでしょうか。
どなたか教えて頂けないでしょうか。

Q2:HUPシグナルは00:02に送信されていて、プロセスダウンが00:10に発生しておりま
す。このタイムラグは何を意味するのでしょうか。

Q3:HUPシグナルはPID 22377のhttpdに送信されております。しかし、ps結果では当該
プロセスの起動時間に変わりません。当該プロセスは再起動していないと言う事でしょうか。
root     22377  0.0  0.4  32452 15372 ?        Ss   Sep13   0:12 /usr/sbin/httpd

[ご参考]
・プログラムX
--- Test_CreateSleepProc.php ---
<?php
exec("php -f Test_Sleep.php > /dev/null &");
?>
---

・プログラムA
--- Test_Sleep.php ---
<?php
$loop_condition	= true ;
$loop_cnt	= 0 ;
while($loop_condition){
	try {
		$ret = sleep(10);
		if ($ret != 0) {
			error_log(__FILE__.' '.__LINE__." sleepエラー発生:".$ret."\n", 3,
"./log/test_sleep.log");
		}
	} catch (Exception $e) {
		$logger->fatal(__FILE__.' '.__LINE__.' プロセススリープ時に例外発生:'.$e) ;
	}
	$loop_cnt++ ;
	error_log(__FILE__.' '.__LINE__." sleep[".$loop_cnt."]\n", 3,
"./log/test_sleep.log");
}
	error_log(__FILE__.' '.__LINE__." プロセス終了:".$loop_condition."\n", 3,
"./log/test_sleep.log");
?>
---

以上


PHP-users メーリングリストの案内