diff options
author | Eric Wong <e@80x24.org> | 2016-02-27 21:31:24 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2016-02-27 21:51:39 +0000 |
commit | 617f35dacbd4e5972bf2d82411b45009bbc79a42 (patch) | |
tree | 0a763db89c81941f16dbd16761a35602f3c723c9 /lib/PublicInbox/Spawn.pm | |
parent | ca885bd5905b7faa9ecb7b0eb02476de1d3a7f88 (diff) | |
download | public-inbox-617f35dacbd4e5972bf2d82411b45009bbc79a42.tar.gz |
This should reduce overhead of spawning git processes from our long-running httpd and nntpd servers.
Diffstat (limited to 'lib/PublicInbox/Spawn.pm')
-rw-r--r-- | lib/PublicInbox/Spawn.pm | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/lib/PublicInbox/Spawn.pm b/lib/PublicInbox/Spawn.pm index aa8d81b3..394a0b45 100644 --- a/lib/PublicInbox/Spawn.pm +++ b/lib/PublicInbox/Spawn.pm @@ -1,10 +1,22 @@ # Copyright (C) 2016 all contributors <meta@public-inbox.org> # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> +# +# This allows vfork to be used for spawning subprocesses if +# PERL_INLINE_DIRECTORY is explicitly defined in the environment. +# Under Linux, vfork can make a big difference in spawning performance +# as process size increases (fork still needs to mark pages for CoW use). +# Currently, we only use this for code intended for long running +# daemons (inside the PSGI code (-httpd) and -nntpd). The short-lived +# scripts (-mda, -index, -learn, -init) either use IPC::run or standard +# Perl routines. + package PublicInbox::Spawn; use strict; use warnings; use base qw(Exporter); -our @EXPORT_OK = qw/which spawn/; +use Symbol qw(gensym); +use PublicInbox::ProcessPipe; +our @EXPORT_OK = qw/which spawn popen_rd/; my $vfork_spawn = <<'VFORK_SPAWN'; #include <sys/types.h> @@ -149,4 +161,24 @@ sub spawn ($;$$) { public_inbox_fork_exec($in, $out, $err, $f, $cmd, \@env); } +sub popen_rd { + my ($cmd, $env, $opts) = @_; + unless (wantarray || defined $vfork_spawn || defined $env) { + open my $fh, '-|', @$cmd or + die('open `'.join(' ', @$cmd) . " pipe failed: $!\n"); + return $fh + } + pipe(my ($r, $w)) or die "pipe: $!\n"; + $opts ||= {}; + my $blocking = $opts->{Blocking}; + $r->blocking($blocking) if defined $blocking; + $opts->{1} = fileno($w); + my $pid = spawn($cmd, $env, $opts); + close $w; + return ($r, $pid) if wantarray; + my $ret = gensym; + tie *$ret, 'PublicInbox::ProcessPipe', $pid, $r; + $ret; +} + 1; |