From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, T_SCC_BODY_TEXT_LINE shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 485451F405 for ; Tue, 30 Jan 2024 07:24:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org; s=selector1; t=1706599441; bh=yBX0Iathhy/8MVMOdYMmhlmim0oDVvnvQhAwwl7sfzw=; h=From:To:Subject:Date:From; b=J/0TpWTIqDmYVPhxYcqY20CK7rPRppmw8R6UvONsJDbs+Ul5x+P5mbpVrfPKmgCF+ 9EZ7Jf5YJedznrV4IXTtGHAlAicVVJMT1rsrxOYE2yCz1FwmrBlu4BimjUszjB44bb 93MME/3vF/u8maPIF7tIl9+5U4Pj+INnLg4AY/aQ= From: Eric Wong To: meta@public-inbox.org Subject: [PATCH] spawn: support some rlimit uses via Inline::C Date: Tue, 30 Jan 2024 07:22:21 +0000 Message-ID: <20240130072221.10323-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: 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 #include @@ -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 .= <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; } }