You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by he...@apache.org on 2022/05/16 15:51:20 UTC

svn commit: r1900961 - in /spamassassin/trunk: ./ lib/Mail/SpamAssassin/ lib/Mail/SpamAssassin/Plugin/

Author: hege
Date: Mon May 16 15:51:19 2022
New Revision: 1900961

URL: http://svn.apache.org/viewvc?rev=1900961&view=rev
Log:
Bug 7987 - DNSEval.pm,HashBL.pm,URILocalBL.pm: unnecessary use of rule_pending and rule_ready
- Remove $pms->rule_pending(), $pms->{tests_pending} to make things much simpler
- Async eval-functions must now "return undef"

Modified:
    spamassassin/trunk/UPGRADE
    spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/ASN.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Check.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DCC.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DNSEval.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/FromNameSpoof.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/HashBL.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Pyzor.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Razor2.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm

Modified: spamassassin/trunk/UPGRADE
URL: http://svn.apache.org/viewvc/spamassassin/trunk/UPGRADE?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/UPGRADE (original)
+++ spamassassin/trunk/UPGRADE Mon May 16 15:51:19 2022
@@ -28,12 +28,11 @@ Note for Users Upgrading to SpamAssassin
 - Meta rules no longer use priority values, they are evaluated dynamically
   when the rules they depend on are finished.  (Bug 7735)
 
-- API: New $pms->rule_pending() and $pms->rule_ready() functions. 
-  $pms->rule_pending($rulename) must be called from rules eval-function, if
-  the result can arrive later than when exiting the function (async
-  lookups).  $pms->rule_ready($rulename) or $pms->got_hit(...) must be
-  called when the result has arrived.  If these are not used, it can break
-  depending meta rule evaluation.
+- API: New $pms->rule_ready() function. Any asynchronous eval-function must
+  now return undef (instead of 0 or 1), if rule result is not ready when
+  exiting the function.  $pms->rule_ready($rulename) or $pms->got_hit(...)
+  must be called when the result has arrived.  If these are not used, it can
+  break depending meta rule evaluation.
 
 - Improved internal header address (From/To/Cc) parser, now also handles
   multiple addresses.  Optional support for external Email::Address::XS

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm Mon May 16 15:51:19 2022
@@ -94,14 +94,14 @@ sub do_rbl_lookup {
   if (defined $subtest) {
     if ($subtest =~ /^sb:/) {
       info("dns: ignored $rule, SenderBase rules are deprecated");
-      return;
+      return 0;
     }
     # Compile as regex if not pure ip/bitmask (same check in process_dnsbl_result)
     if ($subtest !~ /^\d+(?:\.\d+\.\d+\.\d+)?$/) {
       my ($rec, $err) = compile_regexp($subtest, 0);
       if (!$rec) {
         warn("dns: invalid rule $rule subtest regexp '$subtest': $err\n");
-        return;
+        return 0;
       }
       $subtest = $rec;
     }
@@ -110,26 +110,25 @@ sub do_rbl_lookup {
   dbg("dns: launching rule %s, set %s, type %s, %s", $rule, $set, $type,
     defined $subtest ? "subtest $subtest" : 'no subtest');
 
-  $self->rule_pending($rule); # mark async
-
   my $ent = {
     rulename => $rule,
     type => "DNSBL",
     set => $set,
     subtest => $subtest,
   };
-  $self->{async}->bgsend_and_start_lookup($host, $type, undef, $ent,
+  my $ret = $self->{async}->bgsend_and_start_lookup($host, $type, undef, $ent,
     sub { my($ent, $pkt) = @_; $self->process_dnsbl_result($ent, $pkt) },
     master_deadline => $self->{master_deadline}
   );
+
+  return 0 if defined $ret; # no query started
+  return; # return undef for async status
 }
 
 # Deprecated, was only used from DNSEval.pm?
 sub do_dns_lookup {
   my ($self, $rule, $type, $host) = @_;
 
-  $self->rule_pending($rule); # mark async
-
   my $ent = {
     rulename => $rule,
     type => "DNSBL",

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm Mon May 16 15:51:19 2022
@@ -294,7 +294,6 @@ sub new {
     'subtest_names_hit' => [ ],
     'spamd_result_log_items' => [ ],
     'tests_already_hit' => { },
-    'tests_pending'     => { },
     'get_cache'         => { },
     'tag_data'          => { },
     'rule_errors'       => 0,
@@ -3104,9 +3103,6 @@ sub got_hit {
     $score = $params{defscore}  if !defined $score;
   }
 
-  # Make sure rule is marked ready in tests_pending also
-  $self->{tests_pending}->{$rule} = 0;
-
   # adding a hit does nothing if we don't have a score -- we probably
   # shouldn't have run it in the first place
   if (!$score) {
@@ -3171,70 +3167,14 @@ sub got_hit {
   return 1;
 }
 
-=item $status->rule_pending ($rulename)
-
-Register a pending rule.  Must be called if the rules result is evaluated
-later than when exiting it's eval-function (e.g.  async lookups).  This is
-required for meta rules that depend on this rule to evaluate correctly.
-
-It is not strictly required when $status->{async}->bgsend_and_start_lookup()
-is used, as that automatically tracks pending DNS rules and also marks them
-ready when the result callback is run.  But when a plugin has dummy stub
-eval-function (examples: check_uridnsbl, check_rbl_sub), then using
-rule_pending() and rule_ready() is necessary.  Otherwise in some cases the
-eval-function could be run before any lookups are launched, and the rule
-would be marked ready too early.
-
-$status->rule_ready($rulename) or $status->got_hit($rulename, ...) must be
-called when the result has arrived.  If these are not used, then any meta
-rules depending on the rule might not evaluate at all.
-
-=cut
-
-# === Bug 7735 technical notes ===
-#
-# Rule readiness status for dynamic meta rules evaluation (Plugins / Check /
-# do_meta_tests) is always tracked by $pms->{tests_already_hit}->{$rule}. 
-# If it exists, then rule is considered run and ready.
-#
-# The public rule_pending() / rule_ready() function pair is meant to be used
-# for any async rules, and they additionally track rule status in
-# $pms->{tests_pending}->{$rule}, which do_meta_tests also checks.  Any
-# rule_pending() call _must_ be accompanied later by rule_ready() or
-# got_hit().  But as bgsend_and_start_lookup() automatically tracks rules
-# too, most of legacy plugins not using these should work correctly - only
-# in some corner cases where a dummy stub eval-function is called early by
-# accident (maybe due to adjusted rule priority) things might break.
-#
-# Any rule regardless of what it is must always be marked ready via
-# $pms->{tests_already_hit} for meta evaluation to work, even if no
-# rule_pending() is called.  If rule has no async methods, it's possible to
-# use $pms->{tests_already_hit} directly for marking, as is done for example
-# by Check.pm for all basic body/header/etc rules (look for
-# $hitsptr->{q{'.$rulename.'}} ||= 0).  As such it's also always safe to
-# call rule_ready() without rule_pending(), it achieves the same.
-
-sub rule_pending {
-  my ($self, $rule) = @_;
-
-  # Ignore if called after rule_pending(), rule_ready() or got_hit(), they
-  # are the only ones that make $self->{tests_pending}->{$rule} exist
-  return if exists $self->{tests_pending}->{$rule};
-
-  # It's possible that tests_already_hit == 0, if some stub eval call was
-  # run early.  It's ok to clear this and pretend it was never run.  We now
-  # rely exclusively on tests_pending and wait for rule_ready() or got_hit()
-  delete $self->{tests_already_hit}->{$rule} if !$self->{tests_already_hit}->{$rule};
-  $self->{tests_pending}->{$rule} = 1;
-}
-
 =item $status->rule_ready ($rulename)
 
-Mark a rule ready, so it can be considered for meta rule evaluation.  Any
-rule regardless of type must always be marked ready when it's finished,
-otherwise any meta rules that depend on it might not evaluate.  If
-$status->rule_pending() was called, then a $stats->rule_ready() call must be
-done, alternatively $status->got_hit() will also mark rule ready.
+Mark an asynchronous rule ready, so it can be considered for meta rule
+evaluation.  Asynchronous rule is a rule whose eval-function returns undef,
+marking that it's not ready yet, expecting results later. 
+$status->rule_ready() must be called later to mark it ready, alternatively
+$status->got_hit() also does this.  If neither is called, then any meta rule
+that depends on this rule might not evaluate.
 
 =cut
 
@@ -3244,11 +3184,9 @@ sub rule_ready {
   if ($self->get_async_pending_rules($rule)) {
     # Can't be ready if there are pending DNS lookups, ignore for now.
     # Make sure tests_pending exist, should not accept rule_pending() anymore
-    $self->{tests_pending}->{$rule} ||= 0;
     return;
   }
 
-  $self->{tests_pending}->{$rule} = 0;
   $self->{tests_already_hit}->{$rule} ||= 0;
 }
 

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/ASN.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/ASN.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/ASN.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/ASN.pm Mon May 16 15:51:19 2022
@@ -586,8 +586,6 @@ sub check_asn {
     return 0;
   }
 
-  $pms->rule_pending($rulename); # mark async
-
   $asn_tag = 'ASN' unless defined $asn_tag;
   $pms->action_depends_on_tags($asn_tag,
     sub { my($pms,@args) = @_;
@@ -595,7 +593,7 @@ sub check_asn {
     }
   );
 
-  return 0;
+  return; # return undef for async status
 }
 
 sub _check_asn {

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Check.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Check.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Check.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Check.pm Mon May 16 15:51:19 2022
@@ -282,20 +282,16 @@ sub do_meta_tests {
   return if $self->{am_compiling}; # nothing to compile here
 
   my $mp = $pms->{meta_pending};
-  my $tp = $pms->{tests_pending};
   my $md = $pms->{conf}->{meta_dependencies};
   my $mt = $pms->{conf}->{meta_tests};
   my $h = $pms->{tests_already_hit};
   my $retry;
 
-  # Get pending DNS async rule list
-  my %pl = map { $_ => 1 } $pms->get_async_pending_rules();
-
 RULE:
   foreach my $rulename (keys %$mp) {
     # Meta is not ready if some dependency has not run yet
     foreach my $deprule (@{$md->{$rulename}||[]}) {
-      if (!exists $h->{$deprule} || $tp->{$deprule} || $pl{$deprule}) {
+      if (!exists $h->{$deprule}) {
         next RULE;
       }
     }
@@ -322,7 +318,6 @@ sub finish_meta_tests {
   return if $self->{am_compiling}; # nothing to compile here
 
   my $mp = $pms->{meta_pending};
-  my $tp = $pms->{tests_pending};
   my $md = $pms->{conf}->{meta_dependencies};
   my $mt = $pms->{conf}->{meta_tests};
   my $h = $pms->{tests_already_hit};
@@ -334,7 +329,7 @@ RULE:
     my %unrun;
     # Meta is not ready if some dependency has not run yet
     foreach my $deprule (@{$md->{$rulename}||[]}) {
-      if (!exists $h->{$deprule} || $tp->{$deprule}) {
+      if (!exists $h->{$deprule}) {
         # Record all unrun deps for second meta evaluation
         $unrun{$deprule} = 1;
       }
@@ -1157,10 +1152,8 @@ sub run_eval_tests {
       next;
     }
 
-    # Make sure rule is marked ready for meta rules using $hitsptr
     $evalstr .= '
     if ($scoresptr->{q{'.$rulename.'}}) {
-      $hitsptr->{q{'.$rulename.'}} ||= 0;
       $rulename = q#'.$rulename.'#;
 ';
  
@@ -1176,13 +1169,13 @@ sub run_eval_tests {
 
     if ($would_log_rules_all) {
       $evalstr .= '
-      dbg("rules-all: running eval rule %s (%s)", q{'.$rulename.'}, q{'.$function.'});
+      dbg("rules-all: running eval rule %s (%s)", $rulename, q{'.$function.'});
       ';
     }
 
     $evalstr .= '
       eval {
-        $result = $self->'.$function.'(@extraevalargs, @{$testptr->{q#'.$rulename.'#}->[1]}); 1;
+        $result = $self->'.$function.'(@extraevalargs, @{$testptr->{$rulename}->[1]}); 1;
       } or do {
         $result = 0;
         die "rules: $@\n"  if index($@, "__alarm__ignore__") >= 0;
@@ -1199,10 +1192,16 @@ sub run_eval_tests {
 ';
     }
 
+    # If eval returns undef, it means rule is running async and $hitsptr
+    # will be set later by rule_ready() or got_hit()
     $evalstr .= '
-      if ($result) {
-        $self->got_hit($rulename, $prepend2desc, ruletype => "eval", value => $result);
-        '.$dbgstr.'
+      if (defined $result) {
+        if ($result) {
+          $self->got_hit($rulename, $prepend2desc, ruletype => "eval", value => $result);
+          '.$dbgstr.'
+        } else {
+          $hitsptr->{$rulename} ||= 0;
+        }
       }
     }
 ';

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DCC.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DCC.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DCC.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DCC.pm Mon May 16 15:51:19 2022
@@ -826,9 +826,7 @@ sub check_dcc {
 
   # async already handling?
   if ($pms->{dcc_async_start}) {
-    my $rulename = $pms->get_current_eval_rule_name();
-    $pms->rule_pending($rulename); # mark async
-    return 0;
+    return; # return undef for async status
   }
 
   return $pms->{dcc_result} if defined $pms->{dcc_result};
@@ -887,9 +885,9 @@ sub check_dcc_reputation_range {
     # Install callback if waiting for async result
     if (!defined $cb_rulename) {
       my $rulename = $pms->get_current_eval_rule_name();
-      $pms->rule_pending($rulename); # mark async
       # array matches check_dcc_reputation_range() argument order
       push @{$pms->{dcc_range_callbacks}}, [undef, $min, $max, $rulename];
+      return; # return undef for async status
     }
   }
 

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DNSEval.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DNSEval.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DNSEval.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DNSEval.pm Mon May 16 15:51:19 2022
@@ -206,7 +206,6 @@ sub _init_rbl_subs {
     }
     dbg("dnseval: initialize check_rbl_sub for rule $rule, set $set, subtest $subtest");
     push @{$pms->{rbl_subs}{$set}}, [$subtest, $rule];
-    $pms->rule_pending($rule); # mark async, rule_ready() done in Dns/process_dnsbl_result
   }
 }
 
@@ -284,8 +283,10 @@ sub check_rbl_accreditor {
     $self->message_accreditor_tag($pms);
   }
   if ($pms->{accreditor_tag}->{$accreditor}) {
-    $self->_check_rbl_backend($pms, $rule, $set, $rbl_server, 'A', $subtest);
+    # return undef for async status
+    return $self->_check_rbl_backend($pms, $rule, $set, $rbl_server, 'A', $subtest);
   }
+
   return 0;
 }
 
@@ -409,15 +410,18 @@ sub _check_rbl_backend {
 
   dbg("dnseval: only inspecting the following IPs: ".join(", ", @ips));
 
+  my $queries;
   foreach my $ip (@ips) {
     if (defined(my $revip = reverse_ip_address($ip))) {
-      $pms->do_rbl_lookup($rule, $set, $type, $revip.'.'.$rbl_server, $subtest)
+      my $ret = $pms->do_rbl_lookup($rule, $set, $type, $revip.'.'.$rbl_server, $subtest);
+      $queries++ if defined $ret;
     }
   }
 
   # note that results are not handled here, hits are handled directly
   # as DNS responses are harvested
-  return 0;
+  return 0 if !$queries; # no query started
+  return; # return undef for async status
 }
 
 sub check_rbl {
@@ -426,7 +430,8 @@ sub check_rbl {
   return 0 if $self->{main}->{conf}->{skip_rbl_checks};
   return 0 if !$pms->is_dns_available();
 
-  $self->_check_rbl_backend($pms, $rule, $set, $rbl_server, 'A', $subtest);
+  # return undef for async status
+  return $self->_check_rbl_backend($pms, $rule, $set, $rbl_server, 'A', $subtest);
 }
 
 sub check_rbl_txt {
@@ -435,14 +440,15 @@ sub check_rbl_txt {
   return 0 if $self->{main}->{conf}->{skip_rbl_checks};
   return 0 if !$pms->is_dns_available();
 
-  $self->_check_rbl_backend($pms, $rule, $set, $rbl_server, 'TXT', $subtest);
+  # return undef for async status
+  return $self->_check_rbl_backend($pms, $rule, $set, $rbl_server, 'TXT', $subtest);
 }
 
 sub check_rbl_sub {
   my ($self, $pms, $rule, $set, $subtest) = @_;
   # just a dummy, _init_rbl_subs/do_rbl_lookup handles the subs
-  $pms->rule_pending($rule); # mark async
-  return 0;
+
+  return; # return undef for async status
 }
 
 # this only checks the address host name and not the domain name because
@@ -453,8 +459,9 @@ sub check_rbl_from_host {
   return 0 if $self->{main}->{conf}->{skip_rbl_checks};
   return 0 if !$pms->is_dns_available();
 
-  $self->_check_rbl_addresses($pms, $rule, $set, $rbl_server,
-    $subtest, $pms->all_from_addrs());
+  # return undef for async status
+  return $self->_check_rbl_addresses($pms, $rule, $set, $rbl_server,
+                                     $subtest, $pms->all_from_addrs());
 }
 
 sub check_rbl_headers {
@@ -472,11 +479,13 @@ sub check_rbl_headers {
     @env_hdr = split(/,/, $conf->{rbl_headers});
   }
 
+  my $queries;
   foreach my $rbl_headers (@env_hdr) {
     my $addr = $pms->get($rbl_headers.':addr', undef);
     if ( defined $addr && $addr =~ /\@([^\@\s]+)/ ) {
-      $self->_check_rbl_addresses($pms, $rule, $set, $rbl_server,
-        $subtest, $addr);
+      my $ret = $self->_check_rbl_addresses($pms, $rule, $set, $rbl_server,
+                                            $subtest, $addr);
+      $queries++ if defined $ret;
     } else {
       my $unsplitted_host = $pms->get($rbl_headers);
       chomp($unsplitted_host);
@@ -489,10 +498,14 @@ sub check_rbl_headers {
           next unless is_fqdn_valid($host);
           next unless $pms->{main}->{registryboundaries}->is_domain_valid($host);
         }
-        $pms->do_rbl_lookup($rule, $set, 'A', "$host.$rbl_server", $subtest);
+        my $ret = $pms->do_rbl_lookup($rule, $set, 'A', "$host.$rbl_server", $subtest);
+        $queries++ if defined $ret;
       }
     }
   }
+
+  return 0 if !$queries; # no query started
+  return; # return undef for async status
 }
 
 =over 4
@@ -513,8 +526,9 @@ sub check_rbl_from_domain {
   return 0 if $self->{main}->{conf}->{skip_rbl_checks};
   return 0 if !$pms->is_dns_available();
 
-  $self->_check_rbl_addresses($pms, $rule, $set, $rbl_server,
-    $subtest, $pms->all_from_addrs_domains());
+  # return undef for async status
+  return $self->_check_rbl_addresses($pms, $rule, $set, $rbl_server,
+                                     $subtest, $pms->all_from_addrs_domains());
 }
 =over 4
 
@@ -548,19 +562,18 @@ sub check_rbl_ns_from {
 
   dbg("dnseval: checking NS for host $domain");
 
-  $pms->rule_pending($rule); # mark async
-
   my $obj = { dom => $domain, rule => $rule, set => $set, rbl_server => $rbl_server, subtest => $subtest };
   my $ent = {
     rulename => $rule, zone => $domain, obj => $obj, type => "URI-NS",
   };
   # dig $dom ns
-  $ent = $pms->{async}->bgsend_and_start_lookup(
+  my $ret = $pms->{async}->bgsend_and_start_lookup(
     $domain, 'NS', undef, $ent,
     sub { my ($ent2,$pkt) = @_;
           $self->complete_ns_lookup($pms, $ent2, $pkt, $domain) },
     master_deadline => $pms->{master_deadline} );
-  return $ent;
+  return 0 if !defined $ret; # no query started
+  return; # return undef for async status
 }
 
 sub complete_ns_lookup {
@@ -624,6 +637,7 @@ sub check_rbl_rcvd {
     }
   }
 
+  my $queries;
   foreach my $host ( @udnsrcvd ) {
     if((defined $host) and ($host ne "")) {
       chomp($host);
@@ -641,10 +655,13 @@ sub check_rbl_rcvd {
       } else {
         dbg("dnseval: checking [$host] / $rule / $set / $rbl_server");
       }
-      $pms->do_rbl_lookup($rule, $set, 'A', "$host.$rbl_server", $subtest);
+      my $ret = $pms->do_rbl_lookup($rule, $set, 'A', "$host.$rbl_server", $subtest);
+      $queries++ if defined $ret;
     }
   }
-  return 0;
+
+  return 0 if !$queries; # no query started
+  return; # return undef for async status
 }
 
 # this only checks the address host name and not the domain name because
@@ -655,8 +672,9 @@ sub check_rbl_envfrom {
   return 0 if $self->{main}->{conf}->{skip_rbl_checks};
   return 0 if !$pms->is_dns_available();
 
-  $self->_check_rbl_addresses($pms, $rule, $set, $rbl_server,
-    $subtest, $pms->get('EnvelopeFrom:addr',undef));
+  # return undef for async status
+  return $self->_check_rbl_addresses($pms, $rule, $set, $rbl_server,
+                                 $subtest, $pms->get('EnvelopeFrom:addr',undef));
 }
 
 sub _check_rbl_addresses {
@@ -679,6 +697,7 @@ sub _check_rbl_addresses {
   }
   return unless scalar keys %hosts;
 
+  my $queries;
   for my $host (keys %hosts) {
     if ($host =~ IS_IP_ADDRESS) {
       next if ($pms->{conf}->{tflags}->{$rule}||'') =~ /\bdomains_only\b/;
@@ -689,8 +708,12 @@ sub _check_rbl_addresses {
       next unless $pms->{main}->{registryboundaries}->is_domain_valid($host);
     }
     dbg("dnseval: checking [$host] / $rule / $set / $rbl_server");
-    $pms->do_rbl_lookup($rule, $set, 'A', "$host.$rbl_server", $subtest);
+    my $ret = $pms->do_rbl_lookup($rule, $set, 'A', "$host.$rbl_server", $subtest);
+    $queries++ if defined $ret;
   }
+
+  return 0 if !$queries; # no async
+  return; # return undef for async status
 }
 
 sub check_dns_sender {
@@ -718,12 +741,14 @@ sub check_dns_sender {
   $host = idn_to_ascii($host);
   dbg("dnseval: checking A and MX for host $host");
 
-  $pms->rule_pending($rule); # mark async
+  my $queries;
+  my $ret = $self->do_sender_lookup($pms, $rule, 'A', $host);
+  $queries++ if defined $ret;
+  $ret = $self->do_sender_lookup($pms, $rule, 'MX', $host);
+  $queries++ if defined $ret;
 
-  $self->do_sender_lookup($pms, $rule, 'A', $host);
-  $self->do_sender_lookup($pms, $rule, 'MX', $host);
-
-  return 0;
+  return 0 if !$queries; # no query started
+  return; # return undef for async status
 }
 
 sub do_sender_lookup {
@@ -733,7 +758,7 @@ sub do_sender_lookup {
     rulename => $rule,
     type => "DNSBL-Sender",
   };
-  $pms->{async}->bgsend_and_start_lookup(
+  return $pms->{async}->bgsend_and_start_lookup(
     $host, $type, undef, $ent, sub {
       my ($ent, $pkt) = @_;
       return if !$pkt; # aborted / timed out

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/FromNameSpoof.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/FromNameSpoof.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/FromNameSpoof.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/FromNameSpoof.pm Mon May 16 15:51:19 2022
@@ -270,12 +270,12 @@ sub _check_eval {
         $pms->rule_ready($rulename);
       }
     };
-    $pms->rule_pending($rulename); # mark async
-    return;
+    return; # return undef for async status
   }
 
   $self->_check_fromnamespoof($pms);
-  return $result->();
+  # make sure not to return undef, as this is not async anymore
+  return $result->() || 0;
 }
 
 sub check_fromname_spoof {

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/HashBL.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/HashBL.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/HashBL.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/HashBL.pm Mon May 16 15:51:19 2022
@@ -516,13 +516,14 @@ sub check_hashbl_emails {
   my $max = $opts->{max} || 10;
   $#filtered_emails = $max-1 if scalar @filtered_emails > $max;
 
-  $pms->rule_pending($rulename); # mark async
-
+  my $queries;
   foreach my $email (@filtered_emails) {
-    $self->_submit_query($pms, $rulename, $email, $list, $opts, $subtest);
+    my $ret = $self->_submit_query($pms, $rulename, $email, $list, $opts, $subtest);
+    $queries++ if defined $ret;
   }
 
-  return 0;
+  return 0 if !$queries; # no query started
+  return; # return undef for async status
 }
 
 sub check_hashbl_uris {
@@ -585,13 +586,14 @@ sub check_hashbl_uris {
   my $max = $opts->{max} || 10;
   $#filtered_uris = $max-1 if scalar @filtered_uris > $max;
 
-  $pms->rule_pending($rulename); # mark async
-
+  my $queries;
   foreach my $furi (@filtered_uris) {
-    $self->_submit_query($pms, $rulename, $furi, $list, $opts, $subtest);
+    my $ret = $self->_submit_query($pms, $rulename, $furi, $list, $opts, $subtest);
+    $queries++ if defined $ret;
   }
 
-  return 0;
+  return 0 if !$queries; # no query started
+  return; # return undef for async status
 }
 
 sub check_hashbl_bodyre {
@@ -670,13 +672,14 @@ sub check_hashbl_bodyre {
   my $max = $opts->{max} || 10;
   $#matches = $max-1 if scalar @matches > $max;
 
-  $pms->rule_pending($rulename); # mark async
-
+  my $queries;
   foreach my $match (@matches) {
-    $self->_submit_query($pms, $rulename, $match, $list, $opts, $subtest);
+    my $ret = $self->_submit_query($pms, $rulename, $match, $list, $opts, $subtest);
+    $queries++ if defined $ret;
   }
 
-  return 0;
+  return 0 if !$queries; # no query started
+  return; # return undef for async status
 }
 
 sub check_hashbl_tag {
@@ -716,13 +719,11 @@ sub check_hashbl_tag {
   # Force uppercase
   $tag = uc($tag);
 
-  $pms->rule_pending($rulename); # mark async
-
   $pms->action_depends_on_tags($tag, sub {
     $self->_check_hashbl_tag($pms, $list, $opts, $tag, $subtest, $rulename);
   });
 
-  return 0;
+  return; # return undef for async status
 }
 
 sub _check_hashbl_tag {
@@ -819,7 +820,7 @@ sub _submit_query {
 
   if (exists $pms->{conf}->{hashbl_ignore}->{lc $value}) {
     dbg("query skipped, ignored string: $value");
-    return 1;
+    return 0;
   }
 
   my $hash = $self->_hash($opts, $value);
@@ -827,7 +828,7 @@ sub _submit_query {
 
   if (exists $pms->{conf}->{hashbl_ignore}->{$hash}) {
     dbg("query skipped, ignored hash: $value");
-    return 1;
+    return 0;
   }
 
   my $type = $list =~ s,/(A|TXT)$,,i ? uc($1) : 'A';
@@ -840,7 +841,7 @@ sub _submit_query {
     value => $value,
     subtest => $subtest,
   };
-  $pms->{async}->bgsend_and_start_lookup($lookup, $type, undef, $ent,
+  return $pms->{async}->bgsend_and_start_lookup($lookup, $type, undef, $ent,
     sub { my ($ent, $pkt) = @_; $self->_finish_query($pms, $ent, $pkt); },
     master_deadline => $pms->{master_deadline}
   );

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Pyzor.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Pyzor.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Pyzor.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Pyzor.pm Mon May 16 15:51:19 2022
@@ -330,7 +330,6 @@ sub check_pyzor {
   ## forking method
 
   $pms->{pyzor_rulename} = $pms->get_current_eval_rule_name();
-  $pms->rule_pending($pms->{pyzor_rulename}); # mark async
 
   # create socketpair for communication
   $pms->{pyzor_backchannel} = Mail::SpamAssassin::SubProcBackChannel->new();
@@ -386,7 +385,7 @@ sub check_pyzor {
     return 0;
   };
 
-  return 0;
+  return; # return undef for async status
 }
 
 sub pyzor_lookup {

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Razor2.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Razor2.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Razor2.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Razor2.pm Mon May 16 15:51:19 2022
@@ -443,7 +443,6 @@ sub check_razor2 {
   ## forking method
 
   $pms->{razor2_rulename} = $pms->get_current_eval_rule_name();
-  $pms->rule_pending($pms->{razor2_rulename}); # mark async
 
   # create socketpair for communication
   $pms->{razor2_backchannel} = Mail::SpamAssassin::SubProcBackChannel->new();
@@ -500,7 +499,7 @@ sub check_razor2 {
     return 0;
   };
 
-  return 0;
+  return; # return undef for async status
 }
 
 sub check_tick {
@@ -652,12 +651,11 @@ sub check_razor2_range {
   # If forked, call back later unless results are in
   if ($self->{main}->{conf}->{razor_fork}) {
     if (!defined $pms->{razor2_result}) {
-      $pms->rule_pending($rulename); # mark async
       dbg("razor2: delaying check_razor2_range call for $rulename");
       # array matches check_razor2_range() argument order
       push @{$pms->{razor2_range_callbacks}},
         [$engine, $min, $max, $rulename];
-      return 0;
+      return; # return undef for async status
     }
   } else {
     # If Razor2 hasn't been checked yet, go ahead and run it.

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm Mon May 16 15:51:19 2022
@@ -343,9 +343,7 @@ sub new {
 # this is just a placeholder; in fact the results are dealt with later	 
 sub check_uridnsbl {
   my ($self, $pms) = @_;
-  my $rulename = $pms->get_current_eval_rule_name();
-  $pms->rule_pending($rulename); # mark async
-  return 0;
+  return; # return undef for async status
 }
 
 # ---------------------------------------------------------------------------
@@ -378,8 +376,6 @@ sub check_dnsbl {
   foreach my $rulename (keys %{$conf->{uridnsbls}}) {
     next if !$conf->{scores}->{$rulename};
 
-    $pms->rule_pending($rulename); # mark async
-
     my $rulecf = $conf->{uridnsbls}->{$rulename};
     my %tfl = map { ($_,1) } split(/\s+/, $conf->{tflags}->{$rulename}||'');
 

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm?rev=1900961&r1=1900960&r2=1900961&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm Mon May 16 15:51:19 2022
@@ -392,26 +392,30 @@ sub check_uri_local_bl {
   # bail out now if dns not available
   return 0 if !$pms->is_dns_available();
 
-  $pms->rule_pending($rulename); # mark async
-
+  my $queries;
   foreach my $host (keys %found_hosts) {
     $host = idn_to_ascii($host);
     dbg("launching A/AAAA lookup for $host");
     # launch dns
-    $pms->{async}->bgsend_and_start_lookup($host, 'A', undef,
+    my $ret = $pms->{async}->bgsend_and_start_lookup($host, 'A', undef,
       { rulename => $rulename, host => $host, type => 'URILocalBL' },
       sub { my($ent, $pkt) = @_; $self->_finish_lookup($pms, $ent, $pkt); },
       master_deadline => $pms->{master_deadline}
     );
+    $queries++ if defined $ret;
     # also IPv6 if database supports
     if ($self->{main}->{geodb}->can('country_v6')) {
-      $pms->{async}->bgsend_and_start_lookup($host, 'AAAA', undef,
+      $ret = $pms->{async}->bgsend_and_start_lookup($host, 'AAAA', undef,
         { rulename => $rulename, host => $host, type => 'URILocalBL' },
         sub { my($ent, $pkt) = @_; $self->_finish_lookup($pms, $ent, $pkt); },
         master_deadline => $pms->{master_deadline}
       );
+      $queries++ if defined $ret;
     }
   }
+
+  return 0 if !$queries; # no query started
+  return; # return undef for async status
 }
 
 sub _finish_lookup {