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 |
} |