View | Details | Raw Unified | Return to bug 41707
Collapse All | Expand All

(-)a/C4/SIP/Trapper.pm (-2 / +20 lines)
Lines 65-73 sub BINMODE { Link Here
65
=cut
65
=cut
66
66
67
$SIG{__DIE__} = sub {
67
$SIG{__DIE__} = sub {
68
    my $msg    = shift;
68
    my $msg = shift;
69
70
    # Check if we are inside an eval
71
    my $logger_method = 'error';
72
    $logger_method = 'warn' if defined $^S && $^S != 0;
73
74
    # Check if error originated from SIP code
75
    my $is_sip_error = 0;
76
    my $i            = 0;    # Start from 0 to check the current caller
77
    while ( my @caller = caller( $i++ ) ) {
78
        if ( $caller[0] =~ /^C4::SIP::/ || $caller[1] =~ /\/C4\/SIP\// ) {
79
            $is_sip_error = 1;
80
            last;
81
        }
82
        last if $i > 10;     # Don't check too deep
83
    }
84
85
    # Only log if it's from SIP code
86
    return unless $is_sip_error;
69
    my $logger = Koha::Logger->get( { interface => 'sip', category => 'STDERR' } );
87
    my $logger = Koha::Logger->get( { interface => 'sip', category => 'STDERR' } );
70
    $logger->error($msg) if $logger;
88
    $logger->$logger_method($msg) if $logger;
71
    die $msg;
89
    die $msg;
72
};
90
};
73
91
(-)a/t/db_dependent/SIP/Trapper.t (-1 / +95 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
use Modern::Perl;
4
use Test::More tests => 8;
5
use Test::MockModule;
6
use Test::NoWarnings;
7
8
# Load SIP modules (this loads Trapper and sets up the DIE handler)
9
use_ok('C4::SIP::Trapper');
10
11
# Verify DIE handler is installed
12
ok( exists $SIG{__DIE__}, "DIE signal handler is installed" );
13
14
# Mock Koha::Logger to capture both warnings and errors
15
my @logged_warnings;
16
my @logged_errors;
17
my $mock_logger = Test::MockModule->new('Koha::Logger');
18
$mock_logger->mock(
19
    'get',
20
    sub {
21
        my $self = bless {}, 'Koha::Logger';
22
        return $self;
23
    }
24
);
25
$mock_logger->mock(
26
    'warn',
27
    sub {
28
        my ( $self, $msg ) = @_;
29
        push @logged_warnings, $msg;
30
    }
31
);
32
$mock_logger->mock(
33
    'error',
34
    sub {
35
        my ( $self, $msg ) = @_;
36
        push @logged_errors, $msg;
37
    }
38
);
39
40
# Create a SIP module that will throw an error
41
{
42
43
    package C4::SIP::TestError;
44
    use Modern::Perl;
45
46
    sub cause_fatal_error {
47
        die "Fatal error in SIP module\n";
48
    }
49
}
50
51
# SIP errors inside eval should be logged as WARNING
52
# The DIE handler checks SIP namespace first, then checks if in eval and logs accordingly
53
@logged_warnings = ();
54
@logged_errors   = ();
55
eval { C4::SIP::TestError::cause_fatal_error(); };
56
57
like( $@, qr/Fatal error in SIP module/, "SIP error was caught by eval" );
58
ok(
59
    scalar(@logged_warnings) > 0 && $logged_warnings[0] =~ /Fatal error in SIP module/,
60
    "SIP error inside eval was logged as WARNING by Trapper"
61
);
62
ok(
63
    scalar(@logged_errors) == 0,
64
    "SIP error inside eval was NOT logged as error (only warning)"
65
);
66
67
# Verify non-SIP errors are never logged
68
{
69
70
    package C4::NOTSIP::TestError;
71
    use Modern::Perl;
72
73
    sub cause_fatal_error {
74
        die "Fatal error in NOTSIP module\n";
75
    }
76
}
77
78
@logged_warnings = ();
79
@logged_errors   = ();
80
eval { C4::NOTSIP::TestError::cause_fatal_error(); };
81
82
# Trapper now checks SIP namespace FIRST, then decides what to log
83
# Non-SIP errors return early and are never logged
84
ok(
85
    scalar(@logged_warnings) == 0 && scalar(@logged_errors) == 0,
86
    "Non-SIP error was NOT logged at all (Trapper filters by namespace first)"
87
);
88
like( $@, qr/Fatal error in NOTSIP module/, "Non-SIP error was still caught by eval" );
89
90
# NOTE: Errors outside eval cannot be tested in a test suite because:
91
# 1. Tests require eval to catch errors to prevent test termination
92
# 2. The DIE handler checks $^S to detect eval context
93
# 3. Outside eval, SIP errors would be logged as ERROR level and re-thrown
94
# To verify production behavior, check SIP logs for uncaught fatal errors
95

Return to bug 41707