on premature exit, try to kill our existing children by sending them

the proper signal and waiting for a bit.

Some scaffolding left (verbose) to allow more precise debugging
This commit is contained in:
espie 2019-05-12 10:37:04 +00:00
parent 8afb9c2bda
commit 73534e9b6e
2 changed files with 82 additions and 6 deletions

View File

@ -1,7 +1,7 @@
#! /usr/bin/perl
# ex:ts=8 sw=4:
# $OpenBSD: dpb,v 1.127 2019/05/08 09:10:54 espie Exp $
# $OpenBSD: dpb,v 1.128 2019/05/12 10:37:04 espie Exp $
#
# Copyright (c) 2010-2013 Marc Espie <espie@openbsd.org>
#
@ -29,7 +29,6 @@ use lib ("$ports1/infrastructure/lib", "$FindBin::Bin/../lib");
package main;
use DPB::State;
use DPB::PkgPath;
use DPB::Core;
@ -97,6 +96,24 @@ sub affinityclass
}
my $subdirlist = {};
my $master_pid = $$;
for my $S (qw(INT HUP TERM QUIT)) {
$SIG{$S} = sub {
if ($$ == $master_pid) {
$> = 0;
DPB::Core->cleanup($S, 0);
# my $g = getpgrp();
# kill $S => -$g; # or ask Core.pm ?
} else {
# print STDERR "Entering $S handler from $$ ($master_pid)\n";
# print STDERR join("\n", DPB::Trace::trace_message()), "\n";
}
$SIG{$S} = 'DEFAULT';
kill $S => $$;
};
}
DPB::Trace->setup(\%SIG);
my $state = DPB::State->new;

View File

@ -1,5 +1,5 @@
# ex:ts=8 sw=4:
# $OpenBSD: Core.pm,v 1.93 2019/05/11 15:31:12 espie Exp $
# $OpenBSD: Core.pm,v 1.94 2019/05/12 10:37:04 espie Exp $
#
# Copyright (c) 2010-2013 Marc Espie <espie@openbsd.org>
#
@ -232,15 +232,74 @@ sub reap_wait
return $class->reap_kid(waitpid(-1, 0));
}
sub dump
{
my $c = shift;
return join(' ', ref($c), ref($c->job), $c->job->name);
}
sub send_signal
{
my ($class, $sig, $h, $verbose) = @_;
while (my ($pid, $core) = each %$h) {
print STDERR "Sending $sig to ".$core->dump, "\n"
if $verbose;
kill $sig => $pid;
}
}
sub wait_for_kill
{
my ($class, $h, $verbose) = @_;
for (my $i = 0; $i < 4;) {
my $kid = waitpid(-1, WNOHANG);
if ($kid > 0) {
my $info = "";
if (exists $h->{$kid}) {
$info = $h->{$kid}->dump;
delete $h->{$kid};
}
print STDERR "Killed $kid $? $info\n" if $verbose;
} elsif ($kid == -1) {
return 1;
} else {
print STDERR "Waiting for children to quit\n";
sleep 5;
$i++;
}
}
return 0;
}
sub cleanup
{
my $class = shift;
my ($class, $sig, $verbose) = @_;
$sig //= 'INT';
local $> = 0;
# collate repos together
my $h = {};
for my $repo ($class->repositories) {
for my $pid (keys %$repo) {
kill INT => $pid;
while (my ($k, $v) = each %$repo) {
$h->{$k} = $v;
}
}
$class->send_signal($sig, $h, $verbose);
return if $class->wait_for_kill($h, $verbose);
return if keys %$h == 0;
if ($verbose) {
for my $pid (keys %$h) {
system {'ps'} ('ps', '-p', $pid, '-o',
'pid,ppid,uid,gid,pgid,command');
}
}
print STDERR "Sending KILL to remaining children\n";
$class->send_signal('KILL', $h, $verbose);
$class->wait_for_kill($h, $verbose);
if (keys %$h > 0) {
print STDERR "Some children still alive, giving up\n";
}
}
sub debug_dump