svn commit: r1936486 - in spamassassin/trunk/lib/Mail: . SpamAssassin
[email protected] Wed, 22 Jul 2026 13:34:40 -0000
| Newsgroups | gmane.mail.spam.spamassassin.cvs |
|---|---|
| Message-ID | <178472728042.606084.12579879836070642654@svn03-he-fi> |
Author: gbechis Date: Wed Jul 22 13:34:40 2026 New Revision: 1936486 Log: Cache eval-plugin glue methods for the process lifetime, not per message PerMsgStatus::finish() undefined every register_plugin_eval_glue() generated wrapper sub (and any register_generated_rule_method() plugin subs) and cleared their tracking hash after every single message, even though this glue is 100% static per-config -- forcing a fresh eval() compile of every distinct eval-plugin function on every message instead of once per process, the same \"compile once, reuse\" pattern Check.pm already uses for its rule subs. It also contradicted register_generated_rule_method()'s documented contract, which says these methods are destroyed at Mail::SpamAssassin::finish() (session end), not per-message. Move the cleanup to Mail::SpamAssassin::finish(), alongside the existing finish_tests plugin-hook cleanup. Since that code runs outside the PerMsgStatus package, bare (non-fully-qualified) method names now need explicit qualification to avoid undefining the wrong symbol. Co-Authored-By: Claude Sonnet 5 <[email protected]> Submitted by: Giovanni <[email protected]> Github: closes #34 Modified: spamassassin/trunk/lib/Mail/SpamAssassin.pm spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm Modified: spamassassin/trunk/lib/Mail/SpamAssassin.pm ============================================================================== --- spamassassin/trunk/lib/Mail/SpamAssassin.pm Wed Jul 22 13:00:29 2026 (r1936485) +++ spamassassin/trunk/lib/Mail/SpamAssassin.pm Wed Jul 22 13:34:40 2026 (r1936486) @@ -1661,6 +1661,25 @@ sub finish { $self->call_plugins("finish_tests", { conf => $self->{conf}, main => $self }); + # clean up eval-plugin glue (register_plugin_eval_glue()) and any + # plugin-registered generated rule methods (register_generated_rule_method()), + # left in place across all messages processed by this session -- see + # the comment in PerMsgStatus::finish() for why these aren't cleaned up + # per-message. register_plugin_eval_glue() pushes bare names (defined in + # the PerMsgStatus package); register_generated_rule_method() pushes + # fully-qualified ones -- qualify bare names here since, unlike + # PerMsgStatus::finish()'s original cleanup loop, this code doesn't run + # in the PerMsgStatus package itself. + { no strict 'refs'; + foreach my $method (@Mail::SpamAssassin::PerMsgStatus::TEMPORARY_METHODS) { + my $fqname = $method =~ /::/ ? $method + : "Mail::SpamAssassin::PerMsgStatus::$method"; + undef &{$fqname} if defined &{$fqname}; + } + } + @Mail::SpamAssassin::PerMsgStatus::TEMPORARY_METHODS = (); + %Mail::SpamAssassin::PerMsgStatus::TEMPORARY_EVAL_GLUE_METHODS = (); + $self->{plugins}->finish(); delete $self->{plugins}; if ($self->{bayes_scanner}) { Modified: spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm ============================================================================== --- spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm Wed Jul 22 13:00:29 2026 (r1936485) +++ spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm Wed Jul 22 13:34:40 2026 (r1936486) @@ -1959,14 +1959,14 @@ sub finish { $self->report_unsatisfied_actions(); - # Clean up temporary methods - foreach my $method (@TEMPORARY_METHODS) { - if (defined &{$method}) { - undef &{$method}; - } - } - @TEMPORARY_METHODS = (); # clear for next time - %TEMPORARY_EVAL_GLUE_METHODS = (); + # Note: @TEMPORARY_METHODS/%TEMPORARY_EVAL_GLUE_METHODS (eval-plugin glue + # generated by register_plugin_eval_glue(), and any methods a plugin + # registered via register_generated_rule_method()) are intentionally NOT + # cleaned up here. They're static per-config, safe to reuse for every + # message scanned by this process -- same lifetime as Check.pm's own + # compiled rule subs. Cleaning them up per-message forced eval-plugin + # glue to be eval()-recompiled on every single message. They're cleaned + # up once at session end, in Mail::SpamAssassin::finish(). # Delete out all of the members of $self. This will remove any direct # circular references and let the memory get reclaimed while also being more