about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@yhbt.net>2020-06-27 10:03:53 +0000
committerEric Wong <e@yhbt.net>2020-06-28 22:27:29 +0000
commita3e57ebf3192885b1928de33c4e07b88f724b052 (patch)
tree5c9fef2e254170147d8a6c4744edbe8568cdea47
parentb82d2eed5248d7e80cae5bfdf418a563ebfba3af (diff)
downloadpublic-inbox-a3e57ebf3192885b1928de33c4e07b88f724b052.tar.gz
Existing use of the $ENV{TAIL} relied on parsing --std{out,err},
which was only usable for read-only daemons.  However, -watch
doesn't use PublicInbox::Daemon code(*), so attempt to figure
out redirects.

(*) -watch won't able to run as a daemon in cases when
    git-credential prompts for IMAP/NNTP passwords.
    PublicInbox::Daemon is also designed for read-only
    parallelism where all worker processes are the same.
    Any subprocesses spawned by -watch are to do specific
    tasks for a particular set of inboxes.
-rw-r--r--lib/PublicInbox/TestCommon.pm22
1 files changed, 17 insertions, 5 deletions
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index 7b4da8b5..b03e93e0 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -276,11 +276,11 @@ sub tick (;$) {
 }
 
 sub wait_for_tail ($;$) {
-        my ($tail_pid, $stop) = @_;
+        my ($tail_pid, $want) = @_;
         my $wait = 2;
         if ($^O eq 'linux') { # GNU tail may use inotify
                 state $tail_has_inotify;
-                return tick if $stop && $tail_has_inotify;
+                return tick if $want < 0 && $tail_has_inotify;
                 my $end = time + $wait;
                 my @ino;
                 do {
@@ -297,7 +297,7 @@ sub wait_for_tail ($;$) {
                                 local $/ = "\n";
                                 @info = grep(/^inotify wd:/, <$fh>);
                         }
-                } while (scalar(@info) < 2 && time <= $end and tick);
+                } while (scalar(@info) < $want && time <= $end and tick);
         } else {
                 sleep($wait);
         }
@@ -337,6 +337,18 @@ sub start_script {
                         next unless /\A--std(?:err|out)=(.+)\z/;
                         push @paths, $1;
                 }
+                if ($opt) {
+                        for (1, 2) {
+                                my $f = $opt->{$_} or next;
+                                if (!ref($f)) {
+                                        push @paths, $f;
+                                } elsif (ref($f) eq 'GLOB' && $^O eq 'linux') {
+                                        my $fd = fileno($f);
+                                        my $f = readlink "/proc/$$/fd/$fd";
+                                        push @paths, $f if -e $f;
+                                }
+                        }
+                }
                 if (@paths) {
                         defined($tail_pid = fork) or die "fork: $!\n";
                         if ($tail_pid == 0) {
@@ -346,7 +358,7 @@ sub start_script {
                                 exec(split(' ', $tail_cmd), @paths);
                                 die "$tail_cmd failed: $!";
                         }
-                        wait_for_tail($tail_pid);
+                        wait_for_tail($tail_pid, scalar @paths);
                 }
         }
         defined(my $pid = fork) or die "fork: $!\n";
@@ -414,7 +426,7 @@ sub DESTROY {
         my ($self) = @_;
         return if $self->{owner} != $$;
         if (my $tail_pid = delete $self->{tail_pid}) {
-                PublicInbox::TestCommon::wait_for_tail($tail_pid, 1);
+                PublicInbox::TestCommon::wait_for_tail($tail_pid, -1);
                 CORE::kill('TERM', $tail_pid);
         }
         $self->join('TERM');