Pcore

 view release on metacpan or  search on metacpan

lib/Pcore/Core/Exception.pm  view on Meta::CPAN

package Pcore::Core::Exception;

use Pcore -export;
use Carp qw[];
use Pcore::Core::Exception::Object;

our $EXPORT = {    #
    DEFAULT => [qw[croak cluck]],
};

our $IGNORE_ERRORS = 1;    # do not write errors to error log channel by default

# needed to properly destruct TEMP_DIR
$SIG->{INT} = AE::signal INT => \&SIGINT;

# required for properly remove TEMP_DIR
$SIG->{TERM} = AE::signal TERM => \&SIGTERM;

$SIG{__DIE__} = \&SIGDIE;    ## no critic qw[Variables::RequireLocalizedPunctuationVars]

$SIG{__WARN__} = \&SIGWARN;  ## no critic qw[Variables::RequireLocalizedPunctuationVars]

# we don't need stacktrace from Error::TypeTiny exceptions
$Error::TypeTiny::StackTrace = 0;

# catch unhandled errors in EV callbacks
$EV::DIED = sub {
    my $e = Pcore::Core::Exception::Object->new( $@, level => 'ERROR', skip_frames => 1, with_trace => 1 );

    {
        local $@;

        eval { $e->sendlog('FATAL') };
    }

    return;
};

# catch unhandled errors in Coro::async threads
$Coro::State::DIEHOOK = sub {
    my $e = Pcore::Core::Exception::Object->new( $_[0], level => 'ERROR', skip_frames => 1, with_trace => 1 );

    # $^S: !defined - parsing module, eval, or main program, true - executing in eval
    if ( !$^S ) {
        {
            local $@;

            eval { $e->sendlog('FATAL') };
        }

        # cancel current coro execution. but not exit the script
        $Coro::current->cancel;
    }
    else {
        CORE::die $e;    # set $@ to $e
    }

    return;
};

# catch warnings both in EV callbacks and Coro::async
$Coro::State::WARNHOOK = sub {
    my $e = Pcore::Core::Exception::Object->new( $_[0], level => 'WARN', skip_frames => 1, with_trace => 1 );

    {
        local $@;

        eval { $e->sendlog('WARN') };
    }

    return;
};

# redefine Carp::longmess, Carp::shotmess, disable stack trace
{
    no warnings qw[redefine];

    *Carp::longmess = *Carp::shortmess = sub {
        if ( defined $_[0] ) {
            return $_[0];
        }
        else {
            return $EMPTY;
        }
    };
}

sub SIGINT { exit 128 + 2 }

sub SIGTERM { exit 128 + 15 }

# SIGNALS
sub SIGDIE {
    my $e = Pcore::Core::Exception::Object->new( $_[0], level => 'ERROR', skip_frames => 1, with_trace => 1 );

    # ERROR, !defined $^S - parsing module, eval, or main program, true - executing in eval
    if ( !defined $^S || $^S ) {
        if ( !$IGNORE_ERRORS ) {
            local $@;

            eval { $e->sendlog('ERROR') };
        }

        return CORE::die $e;    # set $@ to $e
    }

    # FATAL
    else {
        {
            local $@;



( run in 1.143 second using v1.01-cache-2.11-cpan-df04353d9ac )