|
@@ -19,13 +19,15 @@
|
|
|
|
|
|
use strict;
|
|
|
use warnings;
|
|
|
+
|
|
|
use Cwd;
|
|
|
+use File::Spec;
|
|
|
use File::Temp qw/tempfile tempdir/;
|
|
|
+use FindBin;
|
|
|
+use Getopt::Long;
|
|
|
+use IO::Handle;
|
|
|
use List::Util qw/reduce/;
|
|
|
use OpenBSD::PackageName;
|
|
|
-use Getopt::Long;
|
|
|
-use FindBin;
|
|
|
-use File::Spec;
|
|
|
use POSIX qw/uname :sys_wait_h :signal_h/;
|
|
|
|
|
|
|
|
@@ -107,20 +109,45 @@ my @aborted = ();
|
|
|
# Hash of reaped child processes
|
|
|
my %reaped_pids = ();
|
|
|
|
|
|
-# pipe to tee for logging
|
|
|
-my $tee = undef;
|
|
|
-
|
|
|
# Default signal handler for SIGCHLD
|
|
|
my $old_child_sigaction = POSIX::SigAction->new();
|
|
|
|
|
|
+# Status variables for the logging / redirect of STDOUT & STDERR
|
|
|
+my ($logpipe, $tee_pid, $stdout_orig, $stderr_orig);
|
|
|
+
|
|
|
# This function will remove the finished forked build from the list of
|
|
|
# currently build ports.
|
|
|
sub REAPER {
|
|
|
while ((my $wpid = waitpid(-1, &WNOHANG)) > 0) {
|
|
|
my $status = $?;
|
|
|
-
|
|
|
$abort = 1 if ($status != 0);
|
|
|
- $reaped_pids{$wpid} = $status;
|
|
|
+
|
|
|
+ if (!defined($tee_pid) || $wpid != $tee_pid) {
|
|
|
+ $reaped_pids{$wpid} = $status;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $tee_pid = undef;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# Cleanup the log redirect to the tee child if
|
|
|
+sub END {
|
|
|
+ if ($logpipe) {
|
|
|
+ close($logpipe);
|
|
|
+ if ($stderr_orig) {
|
|
|
+ close(STDERR);
|
|
|
+ open(STDERR, '>&', $stderr_orig);
|
|
|
+ }
|
|
|
+ if ($stdout_orig) {
|
|
|
+ close(STDOUT);
|
|
|
+ open(STDOUT, '>&', $stdout_orig);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ($tee_pid) {
|
|
|
+ waitpid($tee_pid, 0);
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
@@ -154,7 +181,6 @@ sub reap {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
# Reads a config file and parses the options set in the config file.
|
|
|
# A list of valid options must be passed to the function.
|
|
|
sub read_rc_file {
|
|
@@ -248,17 +274,51 @@ sub setup_logging {
|
|
|
if (defined $config->{logging} && $config->{logging} == 1) {
|
|
|
my $tmpdir = $ENV{TMPDIR} ? $ENV{TMPDIR} : '/tmp';
|
|
|
$logdir = tempdir("$tmpdir/autoupdate.XXXXXXXXXX");
|
|
|
+ my $logfile = $logdir . '/autoupdate.log';
|
|
|
+
|
|
|
+ pipe my $pipe_out, $logpipe
|
|
|
+ or die "Unable to create pipe: $!\n";
|
|
|
+ my $pid = fork();
|
|
|
+ if (! defined($pid)) {
|
|
|
+ die "Unable to fork: $!\n";
|
|
|
+ }
|
|
|
+ if ($pid == 0) {
|
|
|
+ # child
|
|
|
+ POSIX::sigaction(&POSIX::SIGCHLD, $old_child_sigaction)
|
|
|
+ or die "Unable to set SIGCHLD handler: $!\n";
|
|
|
+
|
|
|
+ close($logpipe)
|
|
|
+ or warn "Unable to close pipe endpoint in child: $!\n";
|
|
|
+ open(STDIN, '<&=', $pipe_out)
|
|
|
+ or die "Unable to reopen STDIN: $!\n";
|
|
|
+
|
|
|
+ exec 'tee', $logfile;
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+ # Parent
|
|
|
+ close($pipe_out)
|
|
|
+ or warn "Unable to close pipe endpoint in parent: $!\n";
|
|
|
|
|
|
- my $logfile = "$logdir/autoupdate.pl.log";
|
|
|
- open $tee, '|-', "tee $logfile"
|
|
|
- or die qq{Unable to open log file "$logfile": $!\n};
|
|
|
- open STDOUT, '>&', $tee
|
|
|
- or die "Unable to redirect STDOUT to log file.\n";
|
|
|
- open STDERR, '>&', $tee
|
|
|
- or die "Unable to redirect STDERR to log file.\n";
|
|
|
+ open($stdout_orig, '>&', \*STDOUT)
|
|
|
+ or die "Unable to save STDOUT: $!\n";
|
|
|
+ open($stderr_orig, '>&', \*STDERR)
|
|
|
+ or die "Unable to save STDERR: $!\n";
|
|
|
|
|
|
- print STDOUT 'Logging builds in "' . $logdir . '"' . "\n";
|
|
|
- print STDOUT 'Using "' . $logfile . '" as mainlog' . "\n";
|
|
|
+ close(STDERR);
|
|
|
+ close(STDOUT);
|
|
|
+
|
|
|
+ $logpipe->autoflush(1);
|
|
|
+
|
|
|
+ open(STDERR, '>&', $logpipe)
|
|
|
+ or die "Unable to reopen STDERR: $!\n";
|
|
|
+ open(STDOUT, '>&', $logpipe)
|
|
|
+ or die "Unable to reopen STDOUT: $!\n";
|
|
|
+
|
|
|
+ STDOUT->autoflush(1);
|
|
|
+ STDERR->autoflush(1);
|
|
|
+
|
|
|
+ print STDOUT qq{Logging builds in "$logdir"\n};
|
|
|
+ print STDOUT qq{Using "$logfile" as mainlog\n};
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
@@ -445,8 +505,8 @@ sub create_package_information {
|
|
|
flavor => $flavor,
|
|
|
pkg => $pkg,
|
|
|
);
|
|
|
- $p{dependencies} = create_dependencies_list(\%p);
|
|
|
$p{jobs} = set_parallel_build(\%p);
|
|
|
+ $p{dependencies} = create_dependencies_list(\%p);
|
|
|
$p{deppkgs}
|
|
|
= create_dependencies_hash($p{dependencies});
|
|
|
$p{pseudo_flavors} = create_pseudo_flavors_list(\%p);
|
|
@@ -612,17 +672,16 @@ sub build_pkg {
|
|
|
|
|
|
print STDOUT "Building $info->{pkg}\n";
|
|
|
my (@log, $logfile, $logfilename);
|
|
|
- open(my $in, '-|', "$cmd 2>&1")
|
|
|
- or die "Unable to make \"$port\"\n";
|
|
|
if (defined $logdir) {
|
|
|
my $tmp = $info->{port};
|
|
|
$tmp .= "_$info->{subdir}" if ($info->{subdir} ne '');
|
|
|
$tmp =~ s/\//_/g;
|
|
|
$logfilename = "$logdir/$tmp.log";
|
|
|
open($logfile, '>>', $logfilename)
|
|
|
- or print STDERR 'Warning: Unable to create log file'
|
|
|
- . " for $info->{pkg}\n";
|
|
|
+ or die "Unable to create log file for $info->{pkg}: $!\n";
|
|
|
}
|
|
|
+ open(my $in, '-|', "$cmd 2>&1")
|
|
|
+ or die qq{Unable to make "$port"\n};
|
|
|
while (<$in>) {
|
|
|
exit 1 if (/^Detected loop/);
|
|
|
|