]>
git.ipfire.org Git - thirdparty/squid.git/blob - tools/helper-mux/helper-mux.pl.in
13 helper-mux - Concurrency protocol multiplexer for Squid helpers
17 B<helper-mux> helper-path [helper-options ...]
21 B<helper-mux> purpose is to relieve some of the burden
22 B<squid> has when dealing with slow helpers. It does so by acting as a
23 middleman between B<squid> and the actual helpers, talking to B<squid> via
24 the multiplexed variant of the helper protocol and to the helpers
25 via the non-multiplexed variant.
27 Helpers are started on demand, and in theory the muxer can handle up to
28 1k helpers per instance. It is up to B<squid> to decide how many helpers
31 The helper can be controlled using various signals:
32 - SIGHUP: dump the state of all helpers to STDERR
40 Path to the helper being multiplexed.
42 =item B<helper-options>
44 Command line options for the helper being multiplexed.
50 B<helper-mux> knows nothing about the actual messages being passed around,
51 and as such cannot yet compensate for broken helpers.
53 It is not yet able to manage dying helpers.
57 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
59 * Squid software is distributed under GPLv2+ license and includes
60 * contributions from numerous individuals and organizations.
61 * Please see the COPYING and CONTRIBUTORS files for details.
63 Copyright (C) Francesco Chemolli <kinkie@squid-cache.org>
65 This program is free software; you can redistribute it and/or modify
66 it under the terms of the GNU General Public License as published by
67 the Free Software Foundation; either version 2 of the License, or
68 (at your option) any later version.
70 This program is distributed in the hope that it will be useful,
71 but WITHOUT ANY WARRANTY; without even the implied warranty of
72 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73 GNU General Public License for more details.
75 You should have received a copy of the GNU General Public License
76 along with this program; if not, write to the Free Software
77 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
81 #mux-ed format: "slot_num non_muxed_request"
85 $Getopt::Std
::STANDARD_HELP_VERSION
=1;
86 getopts
('h', \
%opts) or die ("unrecognized options");
87 if (defined $opts{h
}) {
91 my $actual_helper_cmd=join(" ",@ARGV);
93 # variables initialization
95 my $helpers_running = 0;
97 vec($rvec,0,1)=1; #stdin
102 $SIG{'HUP'}=\
&dump_state
;
103 $SIG{'CHLD'}=\
&reaper
;
104 # TODO: signal handling for child dying
109 print STDERR
"selecting\n";
110 $nfound=select($rd=$rvec,undef,undef,undef);
111 #$nfound=select($rd=$rvec,undef,$cl=$rvec,undef);
112 print STDERR
"nfound: $nfound\n";
113 if ($nfound == -1 ) {
114 print STDERR
"error in select: $!\n";
115 if ($!{ERESTART
} || $!{EAGAIN
} || $!{EINTR
}) {
120 #print STDERR "cl: ", unpack("b*", $cl) ,"\n";
121 print STDERR
"rd: ", unpack("b*", $rd) ,"\n";
123 #if (vec($cl,0,1)==1) { #stdin was closed
124 # print STDERR "stdin closed\n";
127 if (vec($rd,0,1)==1) { #got stuff from stdin
128 #TODO: handle leftover buffers? I hope that 40kb are enough..
129 $nread=sysread(STDIN
,$_,40960); # read 40kb
130 # clear the signal-bit, stdin is special
133 print STDERR
"nothing read from stdin\n";
136 foreach $req (split("\n",$_ )) {
137 dispatch_request
($req);
140 # find out if any filedesc was closed
142 #TODO: better handle helper restart
143 print STDERR
"helper crash?";
146 #TODO: is it possible to test the whole bitfield in one go?
148 foreach $h (keys %helpers) {
149 my %hlp=%{$helpers{$h}};
150 #print STDERR "examining helper slot $h, fileno $hlp{fno}, filemask ", vec($rd,$hlp{fno},1) , "\n";
151 if (vec($rd,$hlp{fno
},1)==1) {
152 #print STDERR "found\n";
153 handle_helper_response
($h);
155 #no need to clear, it will be reset when iterating
159 sub dispatch_request
{
163 #print STDERR "dispatching request $_";
164 $line =~ /^(\d+) (.*)$/;
170 foreach $slot ( 1 .. ($helpers_running)) {
171 if (!defined($helpers{$slot}->{lastcmd
})) {
172 $h = $helpers{$slot};
178 $helpers_running = $helpers_running + 1;
179 $helpers{$helpers_running}=init_subprocess
();
180 $h = $helpers{$helpers_running};
181 # print STDERR "Now $helpers_running helpers running\n";
191 # gets in a slot number having got some response.
192 # reads the response from the helper and sends it back to squid
193 # prints the response back
194 sub handle_helper_response
{
197 $nread=sysread($helpers{$h}->{rh
},$resp,40960);
198 #print STDERR "got $resp from slot $h\n";
199 print $helpers{$h}->{reqId
}, " ", $resp;
200 delete $helpers{$h}->{lastcmd
};
203 # a subprocess is a hash with members:
207 # fno => file number of the read handle
208 # lastcmd => the command "in flight"
209 # a ref to such a hash is returned by this call
210 sub init_subprocess
{
213 $pid=open2
($rh,$wh,$actual_helper_cmd);
215 die "Failed to fork helper process";
223 $rv{fno
}=fileno($rh);
224 print STDERR
"fileno is $rv{fno}\n";
225 vec($rvec,$rv{fno
},1)=1;
234 the actual helper executable and its arguments.
235 it's advisable to prefix it with "--" to avoid confusion
240 $SIG{'HUP'}=\
&dump_state
;
241 print STDERR
"Helpers state:\n",Dumper
(\
%helpers),"\n";
244 # finds and returns the slot number of a helper, -1 if not found
245 # args: - key in helpers
246 # - value to look for
247 sub find_helper_slot
{
249 foreach (keys %helpers) {
250 return $_ if $helpers{$k}==$v;
257 print STDERR
"child $child died\n";
258 $SIG{'CHLD'}=\
&reaper
;
259 $slot = find_helper_slot
('pid',$child);
260 print STDERR
"slot is $slot\n";
261 #TODO: find the died child, if it was mid-process through a request
262 # send a "BH" to squid and de-init its data-structs here