dポイントプレゼントキャンペーン実施中!

WindowsのActivePerl5.6を使っています。dieやdieやPerl自体でエラーが発生したときに、通常なら標準エラーに出力して、abortされるが、標準エラーを出力する前に独自の関数を実行させて終わらせることは可能でしょうか?

例えば、以下は可能でしょうか?

sub myerror{
print "フック?\n";
goto MyJump;
}

print "TEST1\n";
die "これを表示させずに、別の処理(フックする方法)" ; # 標準エラーが出力されて終わる。

MyJump:
print "TEST2 ここまで表示\n";


Linuxならできるのでしょうか?

A 回答 (4件)

> やはり、Windows環境ではwhile(1){}のループをCTRL+Cで止めた場合はは補足できないのですね。



WindowsでPerlを使う機会があまりないので詳しく調べたことがなかったのですが、ちょっと試してみたところ、手元の環境では Ctrl+C は捕捉できるようです。
- Windows 98/XP
- Perl 5.8.0

# Ctrl+C 用のシグナルハンドラを定義
$SIG{INT} = sub {
  print "SIG_INT\n";
  $loop = 0;
};

$loop = 1;
while ($loop) {
  print "*\n";
  sleep 1;
}

> 良くあるPerlのDBIで返すエラーなどは補足ができるのでしょうか?

これは eval で捕捉可能です。
詳しくはこちらをご覧ください。
http://member.nifty.ne.jp/hippo2000/perltips/dbi …
http://member.nifty.ne.jp/hippo2000/perltips/dbi …

> Windows上で補足できなくて困る割り込みはソフトウェア割り込み以外のハードウェア割り込み?っていうことでしょうか?

試しに他のプロセスから SIG_TERM を送ってみたところ、捕捉されずに終了してしまいました。捕捉できるかどうかは、割り込みの発生源には関係ないようです。どちらにしても不便なことに変わりありませんが。
    • good
    • 0

die を捕捉して終了処理をフックするには、$SIG{__DIE__} を利用します。


プログラムの先頭などで
  $SIG{__DIE__} = \&myerror;
としておけば、die で死ぬ前に myerror が実行されます。
myerror には die のパラメータが引数として渡され、実行後は通常通り、STDERR へのメッセージ出力とともにプログラムが終了します。

また、myerror による共通の例外処理以外に、die のケースごとにカスタマイズされた例外処理を行いたい場合は、evalブロックを併用します。

例:
# 共通の例外処理
sub myerror{
  print "myerror: @_";
}
$SIG{__DIE__} = \&myerror;

eval {
  die "Dying message\n";
  print "このprint文は実行されません。";
};
# このevalブロック専用の例外処理
if ($@) {
  print "exception: $@";
  exit;  # exitしなければ、その後の処理を継続できます。
}

# 実行結果
myerror: Dying message
exception: Dying message

※evalブロック内で die すると、die のパラメータが $@ に設定されてブロックを抜けます。プログラムは終了されず、STDERR へのメッセージ出力もありません。
※$SIG{__DIE__} も evalブロックも、プラットフォームに依らず利用できます。

なお、No.1 で特殊サブルーチン END を使った方法が紹介されていますが、END はプログラム終了時に必ず実行されてしまうので、die に限定した処理を行うことはできません。
    • good
    • 0
この回答へのお礼

ありがとうございます。
やはり、Windows環境ではwhile(1){}のループをCTRL+Cで止めた場合はは補足できないのですね。

良くあるPerlのDBIで返すエラーなどは補足ができるのでしょうか?
Windows上で補足できなくて困る割り込みはソフトウェア割り込み以外のハードウェア割り込み?っていうことでしょうか?無知ですみません。

お礼日時:2004/08/29 09:30

evalを使った例外処理の方法もあります。


Javaのtry/catchの様な感じです。

例)-------------------------------------------
eval {
print "TEST1\n";
die;
};
if ($@) {
# エラーが発生したときの処理
print "TEST2 ここまで表示\n";
exit();
}
----------------------------------------------

evalのブロックの中で例外が発生した場合、ブロック中のコードの実行は終了し、$@にエラーメッセージが設定されます。ただし、シグナルやパニックの様なエラーは捕捉出来ないようです。

evalの引数にはブロックと文字列が取れますが、文字列形式ではevalを実行するたびにコンパイルが行われて負荷が高くなるので、出来るだけブロック形式をとったほうが良いでしょう。
    • good
    • 0

・die、例外発生等でインタプリタが終了するとき(シグナルによる終了は除く)



END { 実行させたい内容 }

・シグナルによる終了時(Unix系列のみ)

$SIG{HUP} = $SIG{INT} = $SIG{PIPE} = $SIG{QUIT} = $SIG{TERM} = \&signal_end;

sub signal_end {
実行させたい内容
}
    • good
    • 0

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