perlが無言で処理を終了してしまう

最近冷房付けなくてもいいなぁと思いつつも、長袖はまだ暑いと思うyukiinu2ndです。
タイトルは「何やら技術的な問題・バグを発見したぞ」という感じですが……残念ながらそんなことはありません。
原因はプログラムの書き方でしたし、Perlに限ったことではないものでした。

お話

あるところに、古くから動いていたプログラムがありました。
少しずつ手は入れられていて、比較的問題なく動いていたプログラムです。
そんなプログラムでしたが、どういうわけかたまにエラーも何も出さずに処理を中断してしまう現象が発生していました。
もちろん、例外処理は入れてありますし、printデバッグも試してみたのですが原因はわからないままでした。

Perlでの例外処理

ここで少し話が逸れますが、Perlでは例外処理機構がありません。
といっても、完全にないわけではなく、evalを利用することで実現します。

eval{
	#ここで例外処理が起きそうなプログラムを書いておく
	$timecard->in($timedat);
};
if($@){
	#もし、eval内でエラーが発生した場合、$@にエラー内容が返ってくる
	if($@ eq 'INVALIDTIME'){
		#時刻データがおかしい!
		print STDERR "時刻のデータが不正です!\n";
	}else{
		print STDERR $@;#エラーをそのままエラー出力に
	}
	exit 1;#終了
}

#……略

sub in {
	my ($self,$timedat) = @_;
	if($timedat !~ /\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}/){
		die "INVALIDTIME";
	}
	#……略
}

このように、eval内に例外が起きそうな処理を書いておき、例外(エラー)が発生したら特殊変数「$@」を確認して例外処理をします。
eval内の処理でdieをすることで例外を投げ、dieした際の文字列で例外処理を分けています。
evalがtryで、if($@)でcatchしてその内部で例外種類によって処理をする、という感じでしょうか。

ちなみに、evalの{}の後ろはセミコロンが必要です。忘れやすいので注意しましょう。

続き

数人が調べてみたものの、原因はわかりませんでした。
調べていく際に見つけた不具合を直しても、この現象は起きる状態が続きました……。
しかし、ある人が気がつきました。

「これ、例外処理握りつぶしてない*1?」

こうして、例外処理部分を直すことで解決しましたとさ。めでたしめでたし。

結局は

正確には握りつぶしていたというよりも、条件に問題があり、何も処理されずに終了するケースがあった、というオチでした。
とりあえず、例外来たらエラーログに出力を行うようにしたので、不具合等があってもすぐに解決できるようになりました。よかったよかった。

ちなみに……

他の言語の例外処理構文try〜catchをPerl上で書けるようにする「Error」というモジュールが存在します。
自分はあまり利用したことがないので、説明は上記CPANページのマニュアルに丸投げします。

*1:例外処理やエラーハンドリングに対して、例外として拾うが何も処理をしないことによってエラー等をなかったことにすること。