about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2021-09-20 13:00:33 +0000
committerEric Wong <e@80x24.org>2021-09-20 19:15:56 +0000
commitc9c1aabe239378e50043e2a3d2e11c4e166cdda0 (patch)
tree5fd8808eccda68e15f1567896ad324f513f489da
parent41c3eed65eb03256b0916cfdbf43723e070a633a (diff)
downloadpublic-inbox-c9c1aabe239378e50043e2a3d2e11c4e166cdda0.tar.gz
We need to waitpid synchronously on pkg-config to use $?.

When loading Gcf2 inside the event loop, implicit dwaitpid
done by PublicInbox::ProcessPipe would not call waitpid in
time to zero $?.  This was causing one of my -httpd to
occasionally fall back to git(1) instead of using Gcf2.

This was noted in:
Link: https://public-inbox.org/meta/20210914085322.25517-1-e@80x24.org/
-rw-r--r--lib/PublicInbox/Gcf2.pm43
1 files changed, 24 insertions, 19 deletions
diff --git a/lib/PublicInbox/Gcf2.pm b/lib/PublicInbox/Gcf2.pm
index 0d31b014..64945ca6 100644
--- a/lib/PublicInbox/Gcf2.pm
+++ b/lib/PublicInbox/Gcf2.pm
@@ -17,36 +17,43 @@ BEGIN {
                 die 'PERL_INLINE_DIRECTORY not defined';
         my $f = "$inline_dir/.public-inbox.lock";
         open my $fh, '+>', $f or die "open($f): $!";
+
+        # CentOS 7.x ships Inline 0.53, 0.64+ has built-in locking
+        flock($fh, LOCK_EX) or die "LOCK_EX($f): $!\n";
+
         my $pc = which($ENV{PKG_CONFIG} // 'pkg-config') //
                 die "pkg-config missing for libgit2";
         my ($dir) = (__FILE__ =~ m!\A(.+?)/[^/]+\z!);
-        my $rdr = {};
-        open $rdr->{2}, '>', '/dev/null' or die "open /dev/null: $!";
+        my $ef = "$inline_dir/.public-inbox.pkg-config.err";
+        open my $err, '+>', $ef or die "open($ef): $!";
         for my $x (qw(libgit2)) {
-                my $l = popen_rd([$pc, '--libs', $x], undef, $rdr);
+                my $rdr = { 2 => $err };
+                my ($l, $pid) = popen_rd([$pc, '--libs', $x], undef, $rdr);
                 $l = do { local $/; <$l> };
+                waitpid($pid, 0);
                 next if $?;
-                my $c = popen_rd([$pc, '--cflags', $x], undef, $rdr);
+                (my $c, $pid) = popen_rd([$pc, '--cflags', $x], undef, $rdr);
                 $c = do { local $/; <$c> };
+                waitpid($pid, 0);
                 next if $?;
 
                 # note: we name C source files .h to prevent
                 # ExtUtils::MakeMaker from automatically trying to
                 # build them.
                 my $f = "$dir/gcf2_$x.h";
-                if (open(my $fh, '<', $f)) {
-                        chomp($l, $c);
-                        local $/;
-                        defined($c_src = <$fh>) or die "read $f: $!";
-                        $CFG{LIBS} = $l;
-                        $CFG{CCFLAGSEX} = $c;
-                        last;
-                } else {
-                        die "E: $f: $!";
-                }
+                open(my $src, '<', $f) or die "E: open($f): $!";
+                chomp($l, $c);
+                local $/;
+                defined($c_src = <$src>) or die "read $f: $!";
+                $CFG{LIBS} = $l;
+                $CFG{CCFLAGSEX} = $c;
+                last;
+        }
+        unless ($c_src) {
+                seek($err, 0, SEEK_SET);
+                $err = do { local $/; <$err> };
+                die "E: libgit2 not installed: $err\n";
         }
-        die "E: libgit2 not installed\n" unless $c_src;
-
         open my $oldout, '>&', \*STDOUT or die "dup(1): $!";
         open my $olderr, '>&', \*STDERR or die "dup(2): $!";
         open STDOUT, '>&', $fh or die "1>$f: $!";
@@ -54,14 +61,12 @@ BEGIN {
         STDERR->autoflush(1);
         STDOUT->autoflush(1);
 
-        # CentOS 7.x ships Inline 0.53, 0.64+ has built-in locking
-        flock($fh, LOCK_EX) or die "LOCK_EX($f): $!\n";
         # we use Capitalized and ALLCAPS for compatibility with old Inline::C
         eval <<'EOM';
 use Inline C => Config => %CFG, BOOT => q[git_libgit2_init();];
 use Inline C => $c_src, BUILD_NOISY => 1;
 EOM
-        my $err = $@;
+        $err = $@;
         open(STDERR, '>&', $olderr) or warn "restore stderr: $!";
         open(STDOUT, '>&', $oldout) or warn "restore stdout: $!";
         if ($err) {