Perl CGI 本当は怖い eval内のループ処理

  • 0
    Like
  • 2
    Comment

    Perlではよく例外処理の代わりにeval を利用していると思います。

    私はいつもこんなコードを書いてCGIで実行していました。
    ※ひとまずコードへのツッコミは無しで^^

    eval {
        $sth = $dbh->prepare(
            "ほにゃららSQL"
        );
        $sth->execute;
        for(my $i=0; $i<$sth->rows; $i++){
            my @row = $sth->fetchrow_array;
            $data[$i]{id} = $row[0];
            $data[$i]{name} = $row[1];
        }
        $sth->finish;
    };
    

    このコードはSQLがエラー無く通った場合、何事もなく処理されます。
    しかし、万が一、生成されたSQL文の文法エラーやMySQLサーバーの異常などで $dbh->prepare() が失敗した場合、どんなことが起きるかというと・・・

    eval関数によってエラーが無視され、メモリを圧迫、放っておくとHTTPDのエラーログが膨大なサイズに膨れ上がって、しまいにはサーバーがダウンします。

    こんなくだらないエラーログだけで28GBまで膨れ上がったerror.logファイル
    image

    原因は単純なコードミス
    何よりダメなのは$sth->prepareが失敗している可能性があるにもかかわらず、$dbh->executeして、さらにはforループの条件式に$sth->rowsを参照している事。
    しかし、$sth->rowsは基本的に参照できないときには-1を返すので、固定SQLなどの絶対失敗しないSQLしかテストしていない場合、このエラーに気づくことはありません。

    気をつけましょう。そしてみんなごめんなさい。