home *** CD-ROM | disk | FTP | other *** search
/ ftp.f-secure.com / 2014.06.ftp.f-secure.com.tar / ftp.f-secure.com / support / hotfix / fsis / IS-SpamControl.fsfix / iufssc / lib / Mail / SpamAssassin / SubProcBackChannel.pm < prev    next >
Text File  |  2006-11-29  |  4KB  |  168 lines

  1. # back-channel for communication between a master and multiple slave processes.
  2. #
  3. # <@LICENSE>
  4. # Licensed to the Apache Software Foundation (ASF) under one or more
  5. # contributor license agreements.  See the NOTICE file distributed with
  6. # this work for additional information regarding copyright ownership.
  7. # The ASF licenses this file to you under the Apache License, Version 2.0
  8. # (the "License"); you may not use this file except in compliance with
  9. # the License.  You may obtain a copy of the License at:
  10. #     http://www.apache.org/licenses/LICENSE-2.0
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. # </@LICENSE>
  17.  
  18. package Mail::SpamAssassin::SubProcBackChannel;
  19.  
  20. use strict;
  21. use warnings;
  22. use bytes;
  23.  
  24. use IO::Socket;
  25. use Mail::SpamAssassin::Util;
  26. use Mail::SpamAssassin::Constants qw(:sa);
  27.  
  28. use vars qw {
  29. };
  30.  
  31. my @ISA = qw();
  32.  
  33. =head1 NAME
  34.  
  35. Mail::SpamAssassin::SubProcBackChannel - back-channel for communication between a master and multiple slave processes
  36.  
  37. =head1 METHODS
  38.  
  39. =over 4
  40.  
  41. =cut
  42.  
  43.  
  44. ###########################################################################
  45.  
  46. sub new {
  47.   my $class = shift;
  48.   $class = ref($class) || $class;
  49.  
  50.   my $self = shift;
  51.   if (!defined $self) { $self = { }; }
  52.   bless ($self, $class);
  53.  
  54.   $self->{kids} = { };
  55.   $self->{fileno_to_fh} = { };
  56.  
  57.   $self;
  58. }
  59.  
  60. ###########################################################################
  61.  
  62. sub set_selector {
  63.   my ($self, $sel) = @_;
  64.   $self->{selector} = $sel;
  65. }
  66.  
  67. sub setup_backchannel_parent_pre_fork {
  68.   my ($self) = @_;
  69.  
  70.   my $io = IO::Socket->new();
  71.   ($self->{latest_kid_fh}, $self->{parent}) =
  72.             $io->socketpair(AF_UNIX,SOCK_STREAM,PF_UNSPEC)
  73.             or die "backchannel: socketpair failed: $!";
  74.  
  75.   # set those to use non-blocking I/O
  76.   $self->{parent}->blocking(0)
  77.             or die "backchannel: set non-blocking failed: $!";
  78.   $self->{latest_kid_fh}->blocking(0)
  79.             or die "backchannel: set non-blocking failed: $!";
  80. }
  81.  
  82. sub setup_backchannel_parent_post_fork {
  83.   my ($self, $pid) = @_;
  84.  
  85.   my $fh = $self->{latest_kid_fh};
  86.  
  87.   close $self->{parent};    # because it's us!
  88.  
  89.   # disable caching for parent<->child relations
  90.   my ($old) = select($fh);
  91.   $|++;
  92.   select($old);
  93.  
  94.   $self->{kids}->{$pid} = $fh;
  95.   $self->add_to_selector($fh);
  96. }
  97.  
  98. sub add_to_selector {
  99.   my ($self, $fh) = @_;
  100.   my $fno = fileno($fh);
  101.   $self->{fileno_to_fh}->{$fno} = $fh;
  102.   vec (${$self->{selector}}, $fno, 1) = 1;
  103. }
  104.  
  105. sub select_vec_to_fh_list {
  106.   my ($self, $vec) = @_;
  107.   my $i = -1;
  108.  
  109.   # grotesque hackery alert! ;)   turn the vec() map of fds into a list of
  110.   # filehandles.  note that filenos that don't have a filehandle in the
  111.   # {fileno_to_fh} hash will be ignored; this is by design, so that other fhs
  112.   # can be selected on using the same vec, and the caller can just check for
  113.   # those in their own code, before they fall back to using this method.
  114.  
  115.   return grep {
  116.         defined
  117.       } map {
  118.         $i++;
  119.         ($_ ? $self->{fileno_to_fh}->{$i} : undef);
  120.       } split (//, unpack ("b*", $vec));
  121. }
  122.  
  123. sub get_socket_for_child {
  124.   my ($self, $pid) = @_;
  125.   return $self->{kids}->{$pid};
  126. }
  127.  
  128. sub delete_socket_for_child {
  129.   my ($self, $pid) = @_;
  130.   delete $self->{kids}->{$pid};
  131. }
  132.  
  133. ###########################################################################
  134.  
  135. sub setup_backchannel_child_post_fork {
  136.   my ($self) = @_;
  137.  
  138.   close $self->{latest_kid_fh}; # because it's us!
  139.  
  140.   my $old = select($self->{parent});
  141.   $| = 1;   # print to parent by default, turn off buffering
  142.   select($old);
  143. }
  144.  
  145. sub get_parent_socket {
  146.   my ($self) = @_;
  147.   return $self->{parent};
  148. }
  149.  
  150. ############################################################################
  151.  
  152. 1;
  153.  
  154. __END__
  155.  
  156. =back
  157.  
  158. =head1 SEE ALSO
  159.  
  160. C<Mail::SpamAssassin>
  161. C<Mail::SpamAssassin::ArchiveIterator>
  162. C<Mail::SpamAssassin::SpamdPreforkScaling>
  163. C<spamassassin>
  164. C<spamd>
  165. C<mass-check>
  166.