* [PATCH] spawn: support some rlimit uses via Inline::C
@ 2024-01-30 7:22 Eric Wong
0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2024-01-30 7:22 UTC (permalink / raw)
To: meta
BSD::Resource isn't packaged for Alpine (as of 3.19), but we
also have optional Inline::C support and already rely on calling
setrlimit(2) directly from the Inline::C version of pi_fork_exec.
---
lib/PublicInbox/ExtSearchIdx.pm | 1 +
lib/PublicInbox/Limiter.pm | 15 +++++++++------
lib/PublicInbox/Spawn.pm | 31 ++++++++++++++++++++++++-------
t/spawn.t | 21 +++++++++++++--------
4 files changed, 47 insertions(+), 21 deletions(-)
diff --git a/lib/PublicInbox/ExtSearchIdx.pm b/lib/PublicInbox/ExtSearchIdx.pm
index 53078124..ebbffffc 100644
--- a/lib/PublicInbox/ExtSearchIdx.pm
+++ b/lib/PublicInbox/ExtSearchIdx.pm
@@ -22,6 +22,7 @@ use Scalar::Util qw(blessed);
use Sys::Hostname qw(hostname);
use File::Glob qw(bsd_glob GLOB_NOSORT);
use PublicInbox::MultiGit;
+use PublicInbox::Spawn ();
use PublicInbox::Search;
use PublicInbox::SearchIdx qw(prepare_stack is_ancestor is_bad_blob);
use PublicInbox::OverIdx;
diff --git a/lib/PublicInbox/Limiter.pm b/lib/PublicInbox/Limiter.pm
index 48a2b6a3..a8d08fc3 100644
--- a/lib/PublicInbox/Limiter.pm
+++ b/lib/PublicInbox/Limiter.pm
@@ -31,14 +31,17 @@ sub setup_rlimit {
} elsif (scalar(@rlimit) != 2) {
warn "could not parse $k: $v\n";
}
- eval { require BSD::Resource };
- if ($@) {
- warn "BSD::Resource missing for $rlim";
- next;
- }
+ my $inf = $v =~ /\binfinity\b/i ?
+ $PublicInbox::Spawn::RLIMITS{RLIM_INFINITY} // eval {
+ require BSD::Resource;
+ BSD::Resource::RLIM_INFINITY();
+ } // do {
+ warn "BSD::Resource missing for $rlim";
+ next;
+ } : undef;
for my $i (0..$#rlimit) {
next if $rlimit[$i] ne 'INFINITY';
- $rlimit[$i] = BSD::Resource::RLIM_INFINITY();
+ $rlimit[$i] = $inf;
}
$self->{$rlim} = \@rlimit;
}
diff --git a/lib/PublicInbox/Spawn.pm b/lib/PublicInbox/Spawn.pm
index e6b12994..e36659ce 100644
--- a/lib/PublicInbox/Spawn.pm
+++ b/lib/PublicInbox/Spawn.pm
@@ -21,10 +21,11 @@ use IO::Handle ();
use Carp qw(croak);
use PublicInbox::IO;
our @EXPORT_OK = qw(which spawn popen_rd popen_wr run_die run_wait run_qx);
-our @RLIMITS = qw(RLIMIT_CPU RLIMIT_CORE RLIMIT_DATA);
+our (@RLIMITS, %RLIMITS);
use autodie qw(close open pipe seek sysseek truncate);
BEGIN {
+ @RLIMITS = qw(RLIMIT_CPU RLIMIT_CORE RLIMIT_DATA);
my $all_libc = <<'ALL_LIBC'; # all *nix systems we support
#include <sys/resource.h>
#include <sys/socket.h>
@@ -283,14 +284,28 @@ void recv_cmd4(PerlIO *s, SV *buf, STRLEN n)
Inline_Stack_Done;
}
#endif /* defined(CMSG_SPACE) && defined(CMSG_LEN) */
-ALL_LIBC
+void rlimit_map()
+{
+ Inline_Stack_Vars;
+ Inline_Stack_Reset;
+ALL_LIBC
my $inline_dir = $ENV{PERL_INLINE_DIRECTORY} // (
$ENV{XDG_CACHE_HOME} //
( ($ENV{HOME} // '/nonexistent').'/.cache' )
).'/public-inbox/inline-c';
undef $all_libc unless -d $inline_dir;
if (defined $all_libc) {
+ for (@RLIMITS, 'RLIM_INFINITY') {
+ $all_libc .= <<EOM;
+ Inline_Stack_Push(sv_2mortal(newSVpvs("$_")));
+ Inline_Stack_Push(sv_2mortal(newSViv($_)));
+EOM
+ }
+ $all_libc .= <<EOM;
+ Inline_Stack_Done;
+} // rlimit_map
+EOM
local $ENV{PERL_INLINE_DIRECTORY} = $inline_dir;
# CentOS 7.x ships Inline 0.53, 0.64+ has built-in locking
my $lk = PublicInbox::Lock->new($inline_dir.
@@ -316,6 +331,7 @@ ALL_LIBC
}
if (defined $all_libc) { # set for Gcf2
$ENV{PERL_INLINE_DIRECTORY} = $inline_dir;
+ %RLIMITS = rlimit_map();
} else {
require PublicInbox::SpawnPP;
*pi_fork_exec = \&PublicInbox::SpawnPP::pi_fork_exec
@@ -361,11 +377,12 @@ sub spawn ($;$$) {
my $rlim = [];
foreach my $l (@RLIMITS) {
my $v = $opt->{$l} // next;
- my $r = eval "require BSD::Resource; BSD::Resource::$l();";
- unless (defined $r) {
- warn "$l undefined by BSD::Resource: $@\n";
- next;
- }
+ my $r = $RLIMITS{$l} //
+ eval "require BSD::Resource; BSD::Resource::$l();" //
+ do {
+ warn "$l undefined by BSD::Resource: $@\n";
+ next;
+ };
push @$rlim, $r, @$v;
}
my $cd = $opt->{'-C'} // ''; # undef => NULL mapping doesn't work?
diff --git a/t/spawn.t b/t/spawn.t
index 48f541b8..5b17ed38 100644
--- a/t/spawn.t
+++ b/t/spawn.t
@@ -6,7 +6,7 @@ use Test::More;
use PublicInbox::Spawn qw(which spawn popen_rd run_qx);
require PublicInbox::Sigfd;
require PublicInbox::DS;
-
+my $rlimit_map = PublicInbox::Spawn->can('rlimit_map');
{
my $true = which('true');
ok($true, "'true' command found with which()");
@@ -192,14 +192,19 @@ EOF
}
SKIP: {
- eval {
- require BSD::Resource;
- defined(BSD::Resource::RLIMIT_CPU())
- } or skip 'BSD::Resource::RLIMIT_CPU missing', 3;
+ if ($rlimit_map) { # Inline::C installed
+ my %rlim = $rlimit_map->();
+ ok defined($rlim{RLIMIT_CPU}), 'RLIMIT_CPU defined';
+ } else {
+ eval {
+ require BSD::Resource;
+ defined(BSD::Resource::RLIMIT_CPU())
+ } or skip 'BSD::Resource::RLIMIT_CPU missing', 3;
+ }
my $cmd = [ $^X, qw(-w -e), <<'EOM' ];
use POSIX qw(:signal_h);
-use BSD::Resource qw(times);
use Time::HiRes qw(time); # gettimeofday
+my $have_bsd_resource = eval { require BSD::Resource };
my $set = POSIX::SigSet->new;
$set->emptyset; # spawn() defaults to blocking all signals
sigprocmask(SIG_SETMASK, $set) or die "SIG_SETMASK: $!";
@@ -211,10 +216,10 @@ while (1) {
# and `write' (via Perl warn)) on otherwise idle systems to
# hit RLIMIT_CPU and fire signals:
# https://marc.info/?i=02A4BB8D-313C-464D-845A-845EB6136B35@gmail.com
- my @t = times;
+ my @t = $have_bsd_resource ? BSD::Resource::times() : (0, 0);
$tot = $t[0] + $t[1];
if (time > $next) {
- warn "# T: @t (utime, ctime, cutime, cstime)\n";
+ warn "# T: @t (utime, ctime, cutime, cstime)\n" if @t;
$next = time + 1.1;
}
}
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2024-01-30 7:24 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-30 7:22 [PATCH] spawn: support some rlimit uses via Inline::C Eric Wong
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).