diff --git a/masses/rule-qa/automc/ruleqa.cgi b/masses/rule-qa/automc/ruleqa.cgi index d1bdce4fb0..234b9237b1 100755 --- a/masses/rule-qa/automc/ruleqa.cgi +++ b/masses/rule-qa/automc/ruleqa.cgi @@ -9,35 +9,10 @@ use warnings; my $PERL_INTERP = $^X; -#---------------------------------------------- -# this is an emergency abuse preventer. 2026-06-25 billcole - -my $eol = "\015\012"; # Use CRLF line ends for headers -open LAF, "; -(my $one, my $five, my $fifteen, my $running, my $iowait) = split (' ', $line); - -if ((($one > 2) || ($fifteen > 6)) && ($ENV{REMOTE_ADDR} ne "127.0.0.1")) { - my $page= q{ - - - - - SpamAssassin Rule QA IS OFFLINE - - - - -

SpamAssassin Rule QA is OFFLINE due to excessive load.

}; - - print "Content-Type: text/html$eol$eol$page\n"; - print "
$ENV{REMOTE_ADDR}
" ; - - exit 0 -} -#--------------------------------------------------- - +# emergency abuse preventer: if true, only requests that actually invoke +# pigz are subject to the load-based offline gate. If false, every request +# is gated on load. +use constant BLOCK_ONLY_ON_PIGZ => 1; our %FREQS_FILENAMES = ( 'DETAILS.age' => 'set 0, broken down by message age in weeks', @@ -57,6 +32,10 @@ $self->ui_parse_url_base(); $self->ui_get_url_switches(); $self->ui_get_daterev(); $self->ui_get_rules(); +if (!BLOCK_ONLY_ON_PIGZ && $self->is_overloaded) { + $self->print_offline_page(); + exit 0; +} $self->show_view(); exit; @@ -295,6 +274,61 @@ sub ui_get_rules { $self->{line_counter} = 0; } +# --------------------------------------------------------------------------- +# emergency abuse preventer. 2026-06-25 billcole; restricted to requests +# that actually invoke pigz, 2026-07-23 + +sub is_overloaded { + my ($self) = @_; + open (my $laf, "; + close $laf; + (my $one, my $five, my $fifteen, my $running, my $iowait) = split (' ', $line); + return ((($one > 2) || ($fifteen > 6)) && ($ENV{REMOTE_ADDR} ne "127.0.0.1")); +} + +sub print_offline_page { + my ($self) = @_; + my $eol = "\015\012"; # Use CRLF line ends for headers + my $page= q{ + + + + + SpamAssassin Rule QA IS OFFLINE + + + + +

SpamAssassin Rule QA is OFFLINE due to excessive load.

}; + + print "Content-Type: text/html$eol$eol$page\n"; + print "
$ENV{REMOTE_ADDR}
" ; +} + +# runs $coderef with STDOUT captured to a buffer, so that if $coderef dies +# with "OVERLOAD_OFFLINE" (raised once we discover, mid-render, that a pigz +# call is actually needed) we can discard the partially-rendered page and +# substitute the offline page instead of sending a broken/duplicate response. +sub render_with_overload_guard { + my ($self, $coderef) = @_; + my $buf = ''; + open(my $bufh, '>', \$buf) or die "cannot open scalar filehandle: $!"; + my $old = select($bufh); + print $self->{q}->header(); + my $ok = eval { $coderef->(); 1 }; + my $err = $@; + select($old); + close $bufh; + if (!$ok && $err =~ /^OVERLOAD_OFFLINE\b/) { + $self->print_offline_page(); + return; + } + die $err if !$ok; + print $buf; +} + # --------------------------------------------------------------------------- # supported views @@ -316,12 +350,10 @@ sub show_view { } elsif ($self->{q}->param('shortdatelist')) { $self->{s_shortdatelist} = 1; - print $self->{q}->header(); - $self->show_default_view(); + $self->render_with_overload_guard(sub { $self->show_default_view() }); } else { - print $self->{q}->header(); - $self->show_default_view(); + $self->render_with_overload_guard(sub { $self->show_default_view() }); } } @@ -802,6 +834,8 @@ sub show_all_sets_for_daterev { sub graph_over_time { my ($self) = @_; + if ($self->is_overloaded) { $self->print_offline_page(); exit 0; } + $self->{datadir} = $self->get_datadir_for_daterev($self->{daterev}); # logs are named e.g. @@ -827,6 +861,8 @@ sub graph_over_time { sub show_mclog { my ($self, $name) = @_; + if ($self->is_overloaded) { $self->print_offline_page(); exit 0; } + print "Content-Type: text/plain\r\n\r\n"; $self->{datadir} = $self->get_datadir_for_daterev($self->{daterev}); @@ -980,6 +1016,7 @@ sub read_freqs_file { if ($file =~ /\.gz$/) { $file =~ s/'//gs; + if ($self->is_overloaded) { die "OVERLOAD_OFFLINE\n"; } if (!open (IN, "pigz -cd < '$file' |")) { warn "cannot read $file"; return;