diff --git a/Parser.pm b/Parser.pm
index c938e8c..8944553 100644
--- a/Parser.pm
+++ b/Parser.pm
@@ -146,8 +146,13 @@ sub parse_start {
my $expatnb = XML::Parser::ExpatNB->new( @expat_options, @_ );
$expatnb->setHandlers(%handlers);
- &$init($expatnb)
- if defined($init);
+ if (defined($init)) {
+ eval { &$init($expatnb) };
+ if ($@) {
+ $expatnb->release;
+ die $@;
+ }
+ }
$expatnb->{_State_} = 1;
@@ -177,8 +182,13 @@ sub parse {
$expat->base( $self->{Base} );
}
- &$init($expat)
- if defined($init);
+ if (defined($init)) {
+ eval { &$init($expat) };
+ if ($@) {
+ $expat->release;
+ die $@;
+ }
+ }
my @result = ();
my $result;
@@ -190,16 +200,22 @@ sub parse {
}
if ( $result and defined($final) ) {
- if (wantarray) {
- @result = &$final($expat);
- }
- else {
- $result = &$final($expat);
- }
+ my $want = wantarray;
+ eval {
+ if ($want) {
+ @result = &$final($expat);
+ }
+ else {
+ $result = &$final($expat);
+ }
+ };
+ $err = $@;
}
$expat->release;
+ die $err if $err;
+
return unless defined wantarray;
return wantarray ? @result : $result;
}
diff --git a/t/parser_api.t b/t/parser_api.t
index d94fdfa..8e57fb1 100644
--- a/t/parser_api.t
+++ b/t/parser_api.t
@@ -213,4 +213,52 @@ my $simple_xml = 'text';
is($p->{Base}, 'saved_base', 'parsefile restores Base even after error');
}
+# --- Init handler die releases parser (no circular ref leak) ---
+{
+ my $released = 0;
+ my $p = XML::Parser->new(
+ Handlers => {
+ Init => sub { die "init failed\n" },
+ },
+ );
+ eval { $p->parse('') };
+ like($@, qr/init failed/, 'Init handler die propagates correctly');
+ # Parser should still be usable after Init failure
+ my $ok = eval {
+ $p->setHandlers(Init => undef);
+ $p->parse('');
+ 1;
+ };
+ ok($ok, 'Parser reusable after Init handler failure');
+}
+
+# --- Final handler die still releases parser ---
+{
+ my $p = XML::Parser->new(
+ Handlers => {
+ Final => sub { die "final failed\n" },
+ },
+ );
+ eval { $p->parse('') };
+ like($@, qr/final failed/, 'Final handler die propagates correctly');
+ # Parser should still be usable
+ my $ok = eval {
+ $p->setHandlers(Final => undef);
+ $p->parse('');
+ 1;
+ };
+ ok($ok, 'Parser reusable after Final handler failure');
+}
+
+# --- parse_start Init handler die releases parser ---
+{
+ my $p = XML::Parser->new(
+ Handlers => {
+ Init => sub { die "init_nb failed\n" },
+ },
+ );
+ eval { $p->parse_start() };
+ like($@, qr/init_nb failed/, 'parse_start Init handler die propagates correctly');
+}
+
done_testing;