MP0

情報技術のこととか

Exception::Tinyを継承したクラスで例外を搬送する時、スタックバックトレースを表示させるにはどうしたらいいのか

Perlでスタックバックトレースを伴った例外を発生させるにはCarp::confessを使えばいいわけですが、 下のコードのようにException::Tinyを継承したクラスで例外を発生させる時にconfessを使ってもスタックバックトレースが表示されません。

package MyApp::Exception;

use strict;
use warnings;
use utf8;
use Carp qw/confess/;
use parent qw/Exception::Tiny/;

sub throw {
    my $class = shift;

    my %args;
    if (@_ == 1) {
        $args{message} = shift;
    } else {
        %args = @_;
    }
    $args{message} = $class unless defined $args{message} && $args{message} ne '';

    ($args{package}, $args{file}, $args{line}) = caller(0);
    $args{subroutine} = (caller(1))[3];

    # die -> confess
    confess $class->new(%args);
}

原因はわかりません!!
他の例外搬送クラスはどうなんでしょうかね。
とりあえず当分evalの中でconfessを呼び出してそれをインスタンス変数に格納する、という強引な方法で対処することにします(

sub throw {
    my $class = shift;

    my %args;
    if (@_ == 1) {
        $args{message} = shift;
    } else {
        %args = @_;
    }
    $args{message} = $class unless defined $args{message} && $args{message} ne '';

    ($args{package}, $args{file}, $args{line}) = caller(0);
    $args{subroutine} = (caller(1))[3];
    
    # confessで例外を発生させてその内容を引数に追加
    eval { confess 'start trace.' };
    $args{trace} = $@;

    die $class->new(%args);
}

追記:

perldoc.jp

ドキュメントはちゃんと読みましょう!! Carpのドキュメント、バグのところにオブジェクトは受けつかないと書いてありますね。 とりあえず上記の方法かlongmessを格納する方法しかなさそうです。 誰かいいモジュールを知っている方がいらっしゃればぜひ教えていただきたいです。