View | Details | Raw Unified | Return to bug 4590
Collapse All | Expand All

(-)lib/Mail/SpamAssassin/SpamdForkScaling.pm (-13 / +27 lines)
Lines 282-288 Link Here
282
282
283
  my ($sock, $kid);
283
  my ($sock, $kid);
284
  while (($kid, $sock) = each %{$self->{backchannel}->{kids}}) {
284
  while (($kid, $sock) = each %{$self->{backchannel}->{kids}}) {
285
    $self->syswrite_with_retry($sock, PF_PING_ORDER) and next;
285
    $self->syswrite_with_retry($sock, PF_PING_ORDER, $kid, 3) and next;
286
286
287
    warn "prefork: write of ping failed to $kid fd=".$sock->fileno.": ".$!;
287
    warn "prefork: write of ping failed to $kid fd=".$sock->fileno.": ".$!;
288
288
Lines 353-359 Link Here
353
      return $self->order_idle_child_to_accept();
353
      return $self->order_idle_child_to_accept();
354
    }
354
    }
355
355
356
    if (!$self->syswrite_with_retry($sock, PF_ACCEPT_ORDER))
356
    if (!$self->syswrite_with_retry($sock, PF_ACCEPT_ORDER, $kid))
357
    {
357
    {
358
      # failure to write to the child; bad news.  call it dead
358
      # failure to write to the child; bad news.  call it dead
359
      warn "prefork: killing rogue child $kid, failed to write on fd ".$sock->fileno.": $!\n";
359
      warn "prefork: killing rogue child $kid, failed to write on fd ".$sock->fileno.": $!\n";
Lines 396-402 Link Here
396
  my ($self, $kid) = @_;
396
  my ($self, $kid) = @_;
397
  if ($self->{waiting_for_idle_child}) {
397
  if ($self->{waiting_for_idle_child}) {
398
    my $sock = $self->{backchannel}->get_socket_for_child($kid);
398
    my $sock = $self->{backchannel}->get_socket_for_child($kid);
399
    $self->syswrite_with_retry($sock, PF_ACCEPT_ORDER)
399
    $self->syswrite_with_retry($sock, PF_ACCEPT_ORDER, $kid)
400
        or die "prefork: $kid claimed it was ready, but write failed on fd ".
400
        or die "prefork: $kid claimed it was ready, but write failed on fd ".
401
                            $sock->fileno.": ".$!;
401
                            $sock->fileno.": ".$!;
402
    $self->{waiting_for_idle_child} = 0;
402
    $self->{waiting_for_idle_child} = 0;
Lines 426-432 Link Here
426
sub report_backchannel_socket {
426
sub report_backchannel_socket {
427
  my ($self, $str) = @_;
427
  my ($self, $str) = @_;
428
  my $sock = $self->{backchannel}->get_parent_socket();
428
  my $sock = $self->{backchannel}->get_parent_socket();
429
  $self->syswrite_with_retry($sock, $str)
429
  $self->syswrite_with_retry($sock, $str, 'parent')
430
        or write "syswrite() to parent failed: $!";
430
        or write "syswrite() to parent failed: $!";
431
}
431
}
432
432
Lines 537-548 Link Here
537
}
537
}
538
538
539
sub syswrite_with_retry {
539
sub syswrite_with_retry {
540
  my ($self, $sock, $buf) = @_;
540
  my ($self, $sock, $buf, $targetname, $numretries) = @_;
541
  $numretries ||= 10;       # default 10 retries
541
542
542
  my $written = 0;
543
  my $written = 0;
544
  my $try = 0;
543
545
544
retry_write:
546
retry_write:
547
548
  $try++;
549
  if ($try > 1) {
550
    warn "prefork: syswrite(".$sock->fileno.") to $targetname failed on try $try";
551
    if ($try > $numretries) {
552
      warn "prefork: giving up";
553
      return undef;
554
    }
555
    else {
556
      # give it 1 second to recover.  we retry indefinitely.
557
      my $rout = '';
558
      vec($rout, $sock->fileno, 1) = 1;
559
      select(undef, $rout, undef, 1);
560
    }
561
  }
562
545
  my $nbytes = $sock->syswrite($buf);
563
  my $nbytes = $sock->syswrite($buf);
564
546
  if (!defined $nbytes) {
565
  if (!defined $nbytes) {
547
    unless ((exists &Errno::EAGAIN && $! == &Errno::EAGAIN)
566
    unless ((exists &Errno::EAGAIN && $! == &Errno::EAGAIN)
548
        || (exists &Errno::EWOULDBLOCK && $! == &Errno::EWOULDBLOCK))
567
        || (exists &Errno::EWOULDBLOCK && $! == &Errno::EWOULDBLOCK))
Lines 551-563 Link Here
551
      return undef;
570
      return undef;
552
    }
571
    }
553
572
554
    warn "prefork: syswrite(".$sock->fileno.") failed, retrying...";
573
    warn "prefork: retrying syswrite(): $!";
555
556
    # give it 5 seconds to recover.  we retry indefinitely.
557
    my $rout = '';
558
    vec($rout, $sock->fileno, 1) = 1;
559
    select(undef, $rout, undef, 5);
560
561
    goto retry_write;
574
    goto retry_write;
562
  }
575
  }
563
  else {
576
  else {
Lines 568-574 Link Here
568
      return $written;      # it's complete, we can return
581
      return $written;      # it's complete, we can return
569
    }
582
    }
570
    else {
583
    else {
571
      warn "prefork: partial write of $nbytes, towrite=".length($buf).
584
      warn "prefork: partial write of $nbytes to ".
585
            $targetname.", towrite=".length($buf).
572
            " sofar=".$written." fd=".$sock->fileno.", recovering";
586
            " sofar=".$written." fd=".$sock->fileno.", recovering";
573
      goto retry_write;
587
      goto retry_write;
574
    }
588
    }

Return to bug 4590