Hallo, dies ist ein Test.
PWD: /www/data-lst1/unixsoft/unixsoft/kaempfer/.public_html
Running in File Mode
Relative path: ./../../../../../../sbin/../squid/libexec/helper-mux
Real path: /usr/squid/libexec/helper-mux
Zurück
#!/usr/perl5/5.36/bin/perl use Getopt::Std; use Data::Dumper; use FileHandle; use IPC::Open2; use Pod::Usage; =pod =head1 NAME helper-mux - Concurrency protocol multiplexer for Squid helpers =head1 SYNOPSIS B<helper-mux> helper-path [helper-options ...] =head1 DESCRIPTION B<helper-mux> purpose is to relieve some of the burden B<squid> has when dealing with slow helpers. It does so by acting as a middleman between B<squid> and the actual helpers, talking to B<squid> via the multiplexed variant of the helper protocol and to the helpers via the non-multiplexed variant. Helpers are started on demand, and in theory the muxer can handle up to 1k helpers per instance. It is up to B<squid> to decide how many helpers to start. The helper can be controlled using various signals: - SIGHUP: dump the state of all helpers to STDERR =head1 OPTIONS =over 8 =item B<helper-path> Path to the helper being multiplexed. =item B<helper-options> Command line options for the helper being multiplexed. =back =head1 KNOWN ISSUES B<helper-mux> knows nothing about the actual messages being passed around, and as such cannot yet compensate for broken helpers. It is not yet able to manage dying helpers. =head1 COPYRIGHT * Copyright (C) 1996-2023 The Squid Software Foundation and contributors * * Squid software is distributed under GPLv2+ license and includes * contributions from numerous individuals and organizations. * Please see the COPYING and CONTRIBUTORS files for details. Copyright (C) Francesco Chemolli <kinkie@squid-cache.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. =cut #mux-ed format: "slot_num non_muxed_request" # options handling my %opts=(); $Getopt::Std::STANDARD_HELP_VERSION=1; getopts('h', \%opts) or die ("unrecognized options"); if (defined $opts{h}) { HELP_MESSAGE(); exit 0; } my $actual_helper_cmd=join(" ",@ARGV); # variables initialization my %helpers=(); my $helpers_running = 0; my $rvec=''; vec($rvec,0,1)=1; #stdin my $nfound; my ($rd,$wr,$cl); # signal handlers $SIG{'HUP'}=\&dump_state; $SIG{'CHLD'}=\&reaper; # TODO: signal handling for child dying # main loop $|=1; while(1) { print STDERR "selecting\n"; $nfound=select($rd=$rvec,undef,undef,undef); #$nfound=select($rd=$rvec,undef,$cl=$rvec,undef); print STDERR "nfound: $nfound\n"; if ($nfound == -1 ) { print STDERR "error in select: $!\n"; if ($!{ERESTART} || $!{EAGAIN} || $!{EINTR}) { next; } exit 1; } #print STDERR "cl: ", unpack("b*", $cl) ,"\n"; print STDERR "rd: ", unpack("b*", $rd) ,"\n"; # stdin is special #if (vec($cl,0,1)==1) { #stdin was closed # print STDERR "stdin closed\n"; # exit(0); #} if (vec($rd,0,1)==1) { #got stuff from stdin #TODO: handle leftover buffers? I hope that 40kb are enough.. $nread=sysread(STDIN,$_,40960); # read 40kb # clear the signal-bit, stdin is special vec($rd,0,1)=0; if ($nread==0) { print STDERR "nothing read from stdin\n"; exit 0; } foreach $req (split("\n",$_ )) { dispatch_request($req); } } # find out if any filedesc was closed if ($cl != 0) { #TODO: better handle helper restart print STDERR "helper crash?"; exit 1; } #TODO: is it possible to test the whole bitfield in one go? # != won't work. foreach $h (keys %helpers) { my %hlp=%{$helpers{$h}}; #print STDERR "examining helper slot $h, fileno $hlp{fno}, filemask ", vec($rd,$hlp{fno},1) , "\n"; if (vec($rd,$hlp{fno},1)==1) { #print STDERR "found\n"; handle_helper_response($h); } #no need to clear, it will be reset when iterating } } sub dispatch_request { my $line=$_[0]; my %h; #print STDERR "dispatching request $_"; $line =~ /^(\d+) (.*)$/; my $reqId=$1; my $req=$2; undef $h; # Find a free helper foreach $slot ( 1 .. ($helpers_running)) { if (!defined($helpers{$slot}->{lastcmd})) { $h = $helpers{$slot}; last; } } # If none create one if (!defined($h)) { $helpers_running = $helpers_running + 1; $helpers{$helpers_running}=init_subprocess(); $h = $helpers{$helpers_running}; # print STDERR "Now $helpers_running helpers running\n"; } $wh=$h->{wh}; $rh=$h->{rh}; $h->{lastcmd}=$req; $h->{reqId}=$reqId; print $wh "$req\n"; } # gets in a slot number having got some response. # reads the response from the helper and sends it back to squid # prints the response back sub handle_helper_response { my $h=$_[0]; my ($nread,$resp); $nread=sysread($helpers{$h}->{rh},$resp,40960); #print STDERR "got $resp from slot $h\n"; print $helpers{$h}->{reqId}, " ", $resp; delete $helpers{$h}->{lastcmd}; } # a subprocess is a hash with members: # pid => $pid # rh => read handle # wh => write handle # fno => file number of the read handle # lastcmd => the command "in flight" # a ref to such a hash is returned by this call sub init_subprocess { my %rv=(); my ($rh,$wh,$pid); $pid=open2($rh,$wh,$actual_helper_cmd); if ($pid == 0) { die "Failed to fork helper process"; } select($rh); $|=1; select($wh); $|=1; select(STDOUT); $rv{rh}=$rh; $rv{wh}=$wh; $rv{pid}=$pid; $rv{fno}=fileno($rh); print STDERR "fileno is $rv{fno}\n"; vec($rvec,$rv{fno},1)=1; return \%rv; } sub HELP_MESSAGE { print STDERR <<EOF $0 options: -h this help message arguments: the actual helper executable and its arguments. it's advisable to prefix it with "--" to avoid confusion EOF } sub dump_state { $SIG{'HUP'}=\&dump_state; print STDERR "Helpers state:\n",Dumper(\%helpers),"\n"; } # finds and returns the slot number of a helper, -1 if not found # args: - key in helpers # - value to look for sub find_helper_slot { my ($k,$v) = @_; foreach (keys %helpers) { return $_ if $helpers{$k}==$v; } return -1; } sub reaper { my $child=wait; print STDERR "child $child died\n"; $SIG{'CHLD'}=\&reaper; $slot = find_helper_slot('pid',$child); print STDERR "slot is $slot\n"; #TODO: find the died child, if it was mid-process through a request # send a "BH" to squid and de-init its data-structs here exit 1; }