X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FSpawnPP.pm;h=25c8c87fd86747ffb9fb7466cd4223d83419813a;hb=9bd675d33ad1e49bd2ebe12a1d216216e61380de;hp=dc2ef364f5b638f4b03169389ec504ab803df0fe;hpb=83770743503dfab6ac337bf053fb22a961c2cb54;p=public-inbox.git diff --git a/lib/PublicInbox/SpawnPP.pm b/lib/PublicInbox/SpawnPP.pm index dc2ef364..25c8c87f 100644 --- a/lib/PublicInbox/SpawnPP.pm +++ b/lib/PublicInbox/SpawnPP.pm @@ -1,15 +1,32 @@ -# Copyright (C) 2016 all contributors +# Copyright (C) 2016-2019 all contributors # License: AGPL-3.0+ + +# Pure-Perl implementation of "spawn". This can't take advantage +# of vfork, so no speedups under Linux for spawning from large processes. package PublicInbox::SpawnPP; use strict; use warnings; -use POSIX qw(dup2); +use POSIX qw(dup2 :signal_h); # Pure Perl implementation for folks that do not use Inline::C -sub public_inbox_fork_exec ($$$$$$) { - my ($in, $out, $err, $f, $cmd, $env) = @_; +sub pi_fork_exec ($$$$$$) { + my ($in, $out, $err, $f, $cmd, $env, $rlim) = @_; + my $old = POSIX::SigSet->new(); + my $set = POSIX::SigSet->new(); + $set->fillset or die "fillset failed: $!"; + sigprocmask(SIG_SETMASK, $set, $old) or die "can't block signals: $!"; + my $syserr; my $pid = fork; + unless (defined $pid) { # compat with Inline::C version + $syserr = $!; + $pid = -1; + } if ($pid == 0) { + while (@$rlim) { + my ($r, $soft, $hard) = splice(@$rlim, 0, 3); + BSD::Resource::setrlimit($r, $soft, $hard) or + warn "failed to set $r=[$soft,$hard]\n"; + } if ($in != 0) { dup2($in, 0) or die "dup2 failed for stdin: $!"; } @@ -19,9 +36,18 @@ sub public_inbox_fork_exec ($$$$$$) { if ($err != 2) { dup2($err, 2) or die "dup2 failed for stderr: $!"; } - exec qw(env -i), @$env, @$cmd; - die "exec env -i ... $cmd->[0] failed: $!\n"; + + if ($ENV{MOD_PERL}) { + exec qw(env -i), @$env, @$cmd; + die "exec env -i ... $cmd->[0] failed: $!\n"; + } else { + local %ENV = map { split(/=/, $_, 2) } @$env; + exec @$cmd; + die "exec $cmd->[0] failed: $!\n"; + } } + sigprocmask(SIG_SETMASK, $old) or die "can't unblock signals: $!"; + $! = $syserr; $pid; }