人生で一番思い出に残ってる靴

PHPスクリプト内にて、ある処理が例えば30秒以上かかった場合は、その瞬間にexit()やエラーをecho()というような
実装をしたいと思うのですが、どのように書けばいいのか思いつきません。

function hoge() {
/* 処理内容 */ //α
return $foo;
}
$foo = hoge(); //β
があった場合、どこに、どのように書けばいいのでしょうか?
簡単に書けば、
$time = time();
if(time() - $time >30) {
echo "時間超過";
}
のような時間的処理分岐を入れたいと思うのですが。
αやβの前に$time = time();を置いたとしても、αの"処理内容"やβの関数実行の後にif(){}節を入れることになるので、
逐次処理のせいで、処理が15分かかった後とかにエラー出力とかになってしまいます。

自分は、何かをスクリプト中で実行し、その処理が30秒を超えた場合はエラーを出したいと考えております。
上記のような分岐方法でなくてもいいのですが、どのように書けばいいのかアドバイス頂けないでしょうか?

A 回答 (3件)

マニュアルに


while setting the set_time_limit(), the duration of sleep() will be ignored in the execution time.
ってあるので、sleep()で実験したのではだめなようです。

ためしに
<?php
set_time_limit(2);
for ( $i = 0 ; $i < 40; $i++) {
  echo "$i:<BR>\n";
  for($j=0;$j<200000;$j++) $k=$i+$j;
}
?>
で実験してみると、、
PHP Fatal error: Maximum execution time of 2 seconds exceeded in {パス} on line 5
のエラーをだしてちゃんと2秒超えたあたりで処理を中断してくれました。
(エラー出すださないは、別途制御できますが)
    • good
    • 0

set_time_limit();


http://php.net/manual/ja/function.set-time-limit …
を使うのが簡単だと 思います。

コールした時点からの経過時間の設定なので
αの処理を最大30秒に制限
βの処理を最大30秒に制限
とそれぞれ設定したいなら、

set_time_limit(30);
α処理
set_time_limit(30)
β処理
って感じです。


タイムアウトしたときにメッセージを出したいなら
register_shutdown_function() で終了時に自動実行するfunctionを登録して、
そのなかで、本来の処理の最後で代入するglobalのフラグ変数をみて、
フラグがセットされてないときは、タイムアウト処理時だとして
その場合のみメッセージを出すようにしてはどうでしょう。
    • good
    • 0
この回答へのお礼

お答え頂きましてありがとうございます。
set_time_limit()を使うという発想はありませんでした。

一応自分でCLIにて(自分は最近CLIで使うことが多いもので)書いてみたのですが、
何故か自分の環境ではset_time_limit()が思ったような挙動をしませんでした。
セーフモードでもないのですが。

<?php
if( !ini_get('safe_mode') ){
set_time_limit(5);
} else {
die("safe_modeですよ\n");
}
function aaa() {
for($i=0; $i<10; $i++) {
echo $i . "秒経過\n";
sleep(1);
}
}
aaa();

サンプルがいまいち良く分からなかったので、単純にこんな感じで買いてみたのですが、
5秒以上かかっても普通に実行されておりました。
使い方が悪いのかもしれませんが。

お礼日時:2012/01/18 23:05

αの具体的な内容や、時間がかかる理由によって、


適切な書き方はまちまちです。

基本的な考え方としては、αの処理を細切れにして、
都度、時間チェックをしてタイムアウト処理をする必要があります。
ループがあれば、その中で毎回時間をチェックして、
30秒を経過した時点で処理を打ち切ります。

また、単体で時間がかかる恐れのある関数には、
多くの場合、タイムアウトを指定するオプションや、
ノンブロッキングモードが提供されています。
例えば http の file_get_contents() であれば、
stream_context_create() で timeout オプションを指定します。
ftp_get() であれば ftp_nb_get() に置き換えます。
ソケット通信であれば stream_set_timeout() や
stream_set_blocking() を使います。

最後に、あまり推奨できませんが、
pcntl_alarm() を使う方法もあります。

$tout=false;

declare(ticks=1);
function sig($sig){global $tout; $tout=true;}

pcntl_signal(SIGALRM, 'sig');
pcntl_alarm(30);

while(!$tout){echo '.'; sleep(1);}
echo "done.\n";
    • good
    • 0
この回答へのお礼

お答えいただきありがとうございます。

確かに単体で時間のかかる処理は時間制御が指定できますね。
自分はこれらの処理をマルチプロセスやらで色々と絡んだものをやろうと思っておりまして、
そこでそのグループにて時間指定をしようかと思っておりました。
もう一度単体での時間制御を見直してスクリプトを考えてみます。

今まで自分にそのような経験が無かっただけで知らないのですが、例えばDBだとか、PECLのmemcacheとかの接続の際とかで何らかの理由で時間がかかった場合はどうなるのでしょうか?
MySQLなどPDOで書いてると、時間制御の為のオプションとかあったかな?とうろ覚えなのですが。
max_execution_timeとかで指定してある時間が過ぎたりすると、全体的にエラーになって、その後に処理の分岐などは出来るのかな、とか今思ったのですが。

pcntl_alarm()、自分は避けていた面もあるのですが、この際ちょっと学習してみます。
教えていただきありがとうございます。

お礼日時:2012/01/18 23:19

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報