Browse Source

Change way of opening tee for logging

Markus Hennecke 1 year ago
parent
commit
543f51f26c
1 changed files with 82 additions and 23 deletions
  1. 82 23
      autoupdate.pl

+ 82 - 23
autoupdate.pl

@@ -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/);