user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
From: Eric Wong <e@80x24.org>
To: meta@public-inbox.org
Subject: [PATCH 2/7] test_common: hoist out tail_f sub
Date: Wed, 13 Oct 2021 10:16:06 +0000	[thread overview]
Message-ID: <20211013101611.22962-3-e@80x24.org> (raw)
In-Reply-To: <20211013101611.22962-1-e@80x24.org>

We'll be reusing this in more places.  While we're at it, allow
it to tail all run_script() users, including lei() in TestCommon.
---
 lib/PublicInbox/TestCommon.pm | 63 ++++++++++++++++++++---------------
 1 file changed, 37 insertions(+), 26 deletions(-)

diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index cd706e0e..57f1db95 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -12,13 +12,14 @@ use IO::Socket::INET;
 use File::Spec;
 our @EXPORT;
 my $lei_loud = $ENV{TEST_LEI_ERR_LOUD};
+my $tail_cmd = $ENV{TAIL};
 our ($lei_opt, $lei_out, $lei_err, $lei_cwdfh);
 BEGIN {
 	@EXPORT = qw(tmpdir tcp_server tcp_connect require_git require_mods
 		run_script start_script key2sub xsys xsys_e xqx eml_load tick
 		have_xapian_compact json_utf8 setup_public_inboxes create_inbox
 		tcp_host_port test_lei lei lei_ok $lei_out $lei_err $lei_opt
-		test_httpd xbail require_cmd is_xdeeply);
+		test_httpd xbail require_cmd is_xdeeply tail_f);
 	require Test::More;
 	my @methods = grep(!/\W/, @Test::More::EXPORT);
 	eval(join('', map { "*$_=\\&Test::More::$_;" } @methods));
@@ -280,11 +281,20 @@ sub run_script ($;$$) {
 	my $sub = $run_mode == 0 ? undef : key2sub($key);
 	my $fhref = [];
 	my $spawn_opt = {};
+	my @tail_paths;
 	for my $fd (0..2) {
 		my $redir = $opt->{$fd};
 		my $ref = ref($redir);
 		if ($ref eq 'SCALAR') {
-			open my $fh, '+>', undef or die "open: $!";
+			my $fh;
+			if ($tail_cmd && $ENV{TAIL_ALL} && $fd > 0) {
+				require File::Temp;
+				$fh = File::Temp->new("fd.$fd-XXXX", TMPDIR=>1);
+				push @tail_paths, $fh->filename;
+			} else {
+				open $fh, '+>', undef;
+			}
+			$fh or xbail $!;
 			$fhref->[$fd] = $fh;
 			$spawn_opt->{$fd} = $fh;
 			next if $fd > 0;
@@ -297,6 +307,7 @@ sub run_script ($;$$) {
 			die "unable to deal with $ref $redir";
 		}
 	}
+	my $tail = @tail_paths ? tail_f(@tail_paths) : undef;
 	if ($key =~ /-(index|convert|extindex|convert|xcpdb)\z/) {
 		unshift @argv, '--no-fsync';
 	}
@@ -337,6 +348,7 @@ sub run_script ($;$$) {
 		umask($umask);
 	}
 
+	{ local $?; undef $tail };
 	# slurp the redirects back into user-supplied strings
 	for my $fd (1..2) {
 		my $fh = $fhref->[$fd] or next;
@@ -355,13 +367,13 @@ sub tick (;$) {
 	1;
 }
 
-sub wait_for_tail ($;$) {
+sub wait_for_tail {
 	my ($tail_pid, $want) = @_;
-	my $wait = 2;
+	my $wait = 2; # "tail -F" sleeps 1.0s at-a-time w/o inotify/kevent
 	if ($^O eq 'linux') { # GNU tail may use inotify
 		state $tail_has_inotify;
-		return tick if $want < 0 && $tail_has_inotify;
-		my $end = time + $wait;
+		return tick if !$want && $tail_has_inotify; # before TERM
+		my $end = time + $wait; # wait for startup:
 		my @ino;
 		do {
 			@ino = grep {
@@ -410,13 +422,23 @@ sub xqx {
 	wantarray ? split(/^/m, $out) : $out;
 }
 
+sub tail_f (@) {
+	$tail_cmd or return; # "tail -F" or "tail -f"
+	for (@_) { open(my $fh, '>>', $_) or die $! };
+	my $cmd = [ split(/ /, $tail_cmd), @_ ];
+	require PublicInbox::Spawn;
+	my $pid = PublicInbox::Spawn::spawn($cmd, undef, { 1 => 2 });
+	wait_for_tail($pid, scalar @_);
+	PublicInboxTestProcess->new($pid, \&wait_for_tail);
+}
+
 sub start_script {
 	my ($cmd, $env, $opt) = @_;
 	my ($key, @argv) = @$cmd;
 	my $run_mode = $ENV{TEST_RUN_MODE} // $opt->{run_mode} // 2;
 	my $sub = $run_mode == 0 ? undef : key2sub($key);
-	my $tail_pid;
-	if (my $tail_cmd = $ENV{TAIL}) {
+	my $tail;
+	if ($tail_cmd) {
 		my @paths;
 		for (@argv) {
 			next unless /\A--std(?:err|out)=(.+)\z/;
@@ -434,17 +456,7 @@ sub start_script {
 				}
 			}
 		}
-		if (@paths) {
-			$tail_pid = fork // die "fork: $!";
-			if ($tail_pid == 0) {
-				# make sure files exist, first
-				open my $fh, '>>', $_ for @paths;
-				open(STDOUT, '>&STDERR') or die "1>&2: $!";
-				exec(split(' ', $tail_cmd), @paths);
-				die "$tail_cmd failed: $!";
-			}
-			wait_for_tail($tail_pid, scalar @paths);
-		}
+		$tail = tail_f(@paths);
 	}
 	my $pid = fork // die "fork: $!\n";
 	if ($pid == 0) {
@@ -480,7 +492,9 @@ sub start_script {
 			die "FAIL: ",join(' ', $key, @argv), ": $!\n";
 		}
 	}
-	PublicInboxTestProcess->new($pid, $tail_pid);
+	my $td = PublicInboxTestProcess->new($pid);
+	$td->{-extra} = $tail;
+	$td;
 }
 
 # favor lei() or lei_ok() over $lei for new code
@@ -735,8 +749,8 @@ use strict;
 sub CLONE_SKIP { 1 }
 
 sub new {
-	my ($klass, $pid, $tail_pid) = @_;
-	bless { pid => $pid, tail_pid => $tail_pid, owner => $$ }, $klass;
+	my ($cls, $pid, $cb) = @_;
+	bless { pid => $pid, cb => $cb, owner => $$ }, $cls;
 }
 
 sub kill {
@@ -747,6 +761,7 @@ sub kill {
 sub join {
 	my ($self, $sig) = @_;
 	my $pid = delete $self->{pid} or return;
+	$self->{cb}->() if defined $self->{cb};
 	CORE::kill($sig, $pid) if defined $sig;
 	my $ret = waitpid($pid, 0) // die "waitpid($pid): $!";
 	$ret == $pid or die "waitpid($pid) != $ret";
@@ -755,10 +770,6 @@ sub join {
 sub DESTROY {
 	my ($self) = @_;
 	return if $self->{owner} != $$;
-	if (my $tail_pid = delete $self->{tail_pid}) {
-		PublicInbox::TestCommon::wait_for_tail($tail_pid, -1);
-		CORE::kill('TERM', $tail_pid);
-	}
 	$self->join('TERM');
 }
 

  parent reply	other threads:[~2021-10-13 10:16 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-04 23:53 httpd memory usage? Eric Wong
2021-09-27  7:10 ` Eric Wong
2021-10-04  0:07 ` [PATCH 0/2] www: fix ref cycles when threading extindex Eric Wong
2021-10-04  0:07   ` [PATCH 1/2] t/thread-cycle: make Email::Simple optional Eric Wong
2021-10-04  0:07   ` [PATCH 2/2] www: fix ref cycle from threading w/ extindex Eric Wong
2021-10-04 22:51   ` [PATCH 0/2] www: fix ref cycles when threading extindex Eric Wong
2021-10-05 11:33     ` Encode.pm leak Eric Wong
2021-10-12 10:59       ` Encode.pm leak in v2.87..v3.12 Eric Wong
2021-10-13 10:16         ` [PATCH 0/7] workaround Encode leak, several test fixes Eric Wong
2021-10-13 10:16           ` [PATCH 1/7] xt/perf-msgview: drop unnecessary use_ok Eric Wong
2021-10-13 10:16           ` Eric Wong [this message]
2021-10-13 10:16           ` [PATCH 3/7] t/www_listing: require opt-in for grokmirror tests Eric Wong
2021-10-13 10:16           ` [PATCH 4/7] eml: avoid Encode 2.87..3.12 leak Eric Wong
2021-10-13 10:16           ` [PATCH 5/7] t/lei-mirror: avoid reading ~/.public-inbox/config in test Eric Wong
2021-10-13 10:16           ` [PATCH 6/7] t/git: avoid "once" warning for async_warn Eric Wong
2021-10-13 10:16           ` [PATCH 7/7] t/nntpd-tls: change diag() to like() assertion Eric Wong
2021-11-04  0:17 ` httpd memory usage? Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://public-inbox.org/README

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211013101611.22962-3-e@80x24.org \
    --to=e@80x24.org \
    --cc=meta@public-inbox.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/public-inbox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).