end0tknr's kipple - 新web写経開発

http://d.hatena.ne.jp/end0tknr/ から移転しました

apache/perlにおけるアプリからのタイムアウト

httpd.confのTimeOutではcgiの処理時間を制限できない?

ある機能の処理時間が長くなった場合、処理を中断させようと、apachehttpd.confにTimeOut (apache2.2ではデフォルト300sec)を設定し、サーバ(perl)側で、sleep() による動作確認を行なっても、httpd.confのTimeOutでは意図した時間にタイムアウトしませんでした。
httpd.apache.org にあるTimeOutのドキュメントを読むと、次のように記載されており、どうやらhttpd.confのTimeOutではcgiの処理時間を制限できないようです。

The TimeOut directive defines the length of time Apache will wait for I/O in various circumstances:
When reading data from the client, the length of time to wait for a TCP packet to arrive if the read buffer is empty.
When writing data to the client, the length of time to wait for an acknowledgement of a packet if the send buffer is full.
In mod_cgi, the length of time to wait for output from a CGI script.
In mod_ext_filter, the length of time to wait for output from a filtering process.
In mod_proxy, the default timeout value if ProxyTimeout is not configured.
http://httpd.apache.org/docs/2.2/en/mod/core.html#timeout

perlであれば、alarm() + evalにより制限可能

どうやら、サーバ側がperlであれば、alarm() と eval を使って次のようにtimeoutを実現出来ます。

eval {
    local $SIG{ALRM} = sub { die "timeout" };
    alarm(5);   #timeout時間設定
    sleep(300); #動作時間を制限したい処理.
};

alarm(0); #timeout制限解除

if ($@) {
    if ($@ =~ /^timeout/) {
        #TODO タイムアウト時の処理. 例えば、DB切断やエラーログ出力
    }
    else {
        #TODO その他エラー時処理
    }
}

その他、jqueryであれば、ajax()のtimeoutオプションで制限可能

次の通りです。

$.ajax({url: 'Seikyu.pl',
        type: 'POST',
        data: {test_key:1},
        timeout: 3000, //←ココ
        success: function(ret_json,txt_status,xhr){
        },
        error: function(ret_json,txt_status,xhr){
        }
       });