user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
From: Eric Wong <e@80x24.org>
To: meta@public-inbox.org
Subject: [PATCH 11/13] qspawn: wire up RLIMIT_* handling to limiters
Date: Tue, 12 Mar 2019 04:00:44 +0000	[thread overview]
Message-ID: <20190312040046.4619-12-e@80x24.org> (raw)
In-Reply-To: <20190312040046.4619-1-e@80x24.org>

This allows users to configure RLIMIT_{CORE,CPU,DATA} using
our "limiter" config directive when spawning external processes.
---
 Documentation/public-inbox-config.pod | 17 +++++++++++
 lib/PublicInbox/Config.pm             |  4 ++-
 lib/PublicInbox/Qspawn.pm             | 41 +++++++++++++++++++++++++--
 lib/PublicInbox/Spawn.pm              |  3 +-
 4 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/Documentation/public-inbox-config.pod b/Documentation/public-inbox-config.pod
index 9647e4a..dae6998 100644
--- a/Documentation/public-inbox-config.pod
+++ b/Documentation/public-inbox-config.pod
@@ -228,12 +228,29 @@ large inboxes, it makes sense to put large inboxes on a named
 limiter with a low max value; while smaller inboxes can use
 the default limiter.
 
+C<RLIMIT_*> keys may be set to enforce resource limits for
+a particular limiter.
+
 =over 8
 
 =item publicinboxlimiter.<name>.max
 
 The maximum number of parallel processes for the given limiter.
 
+=item publicinboxlimiter.<name>.rlimitCore
+
+=item publicinboxlimiter.<name>.rlimitCPU
+
+=item publicinboxlimiter.<name>.rlimitData
+
+The maximum core size, CPU time, or data size processes run with the
+given limiter will use.  This may be comma-separated to distinguish
+soft and hard limits.  The word "INFINITY" is accepted as the
+RLIM_INFINITY constant (if supported by your OS).
+
+See L<setrlimit(2)> for more info on the behavior of RLIMIT_CORE,
+RLIMIT_CPU, and RLIMIT_DATA for you operating system.
+
 =back
 
 =head3 EXAMPLE WITH NAMED LIMITERS
diff --git a/lib/PublicInbox/Config.pm b/lib/PublicInbox/Config.pm
index 15664c6..0f7485f 100644
--- a/lib/PublicInbox/Config.pm
+++ b/lib/PublicInbox/Config.pm
@@ -133,7 +133,9 @@ sub limiter {
 	$self->{-limiters}->{$name} ||= do {
 		require PublicInbox::Qspawn;
 		my $max = $self->{"publicinboxlimiter.$name.max"};
-		PublicInbox::Qspawn::Limiter->new($max);
+		my $limiter = PublicInbox::Qspawn::Limiter->new($max);
+		$limiter->setup_rlimit($name, $self);
+		$limiter;
 	};
 }
 
diff --git a/lib/PublicInbox/Qspawn.pm b/lib/PublicInbox/Qspawn.pm
index 509a441..79cdae7 100644
--- a/lib/PublicInbox/Qspawn.pm
+++ b/lib/PublicInbox/Qspawn.pm
@@ -43,10 +43,18 @@ sub new ($$$;) {
 sub _do_spawn {
 	my ($self, $cb) = @_;
 	my $err;
+	my ($cmd, $env, $opts) = @{$self->{args}};
+	my %opts = %{$opts || {}};
+	my $limiter = $self->{limiter};
+	foreach my $k (PublicInbox::Spawn::RLIMITS()) {
+		if (defined(my $rlimit = $limiter->{$k})) {
+			$opts{$k} = $rlimit;
+		}
+	}
 
-	($self->{rpipe}, $self->{pid}) = popen_rd(@{$self->{args}});
+	($self->{rpipe}, $self->{pid}) = popen_rd($cmd, $env, \%opts);
 	if (defined $self->{pid}) {
-		$self->{limiter}->{running}++;
+		$limiter->{running}++;
 	} else {
 		$self->{err} = $!;
 	}
@@ -251,9 +259,38 @@ sub new {
 		max => $max || 32,
 		running => 0,
 		run_queue => [],
+		# RLIMIT_CPU => undef,
+		# RLIMIT_DATA => undef,
+		# RLIMIT_CORE => undef,
 	}, $class;
 }
 
+sub setup_rlimit {
+	my ($self, $name, $config) = @_;
+	foreach my $rlim (PublicInbox::Spawn::RLIMITS()) {
+		my $k = lc($rlim);
+		$k =~ tr/_//d;
+		$k = "publicinboxlimiter.$name.$k";
+		defined(my $v = $config->{$k}) or next;
+		my @rlimit = split(/\s*,\s*/, $v);
+		if (scalar(@rlimit) == 1) {
+			push @rlimit, $rlimit[0];
+		} elsif (scalar(@rlimit) != 2) {
+			warn "could not parse $k: $v\n";
+		}
+		eval { require BSD::Resource };
+		if ($@) {
+			warn "BSD::Resource missing for $rlim";
+			next;
+		}
+		foreach my $i (0..$#rlimit) {
+			next if $rlimit[$i] ne 'INFINITY';
+			$rlimit[$i] = BSD::Resource::RLIM_INFINITY();
+		}
+		$self->{$rlim} = \@rlimit;
+	}
+}
+
 # captures everything into a buffer and executes a callback when done
 package PublicInbox::Qspawn::Qx;
 use strict;
diff --git a/lib/PublicInbox/Spawn.pm b/lib/PublicInbox/Spawn.pm
index 202cfca..fd98160 100644
--- a/lib/PublicInbox/Spawn.pm
+++ b/lib/PublicInbox/Spawn.pm
@@ -18,6 +18,7 @@ use Symbol qw(gensym);
 use IO::Handle;
 use PublicInbox::ProcessPipe;
 our @EXPORT_OK = qw/which spawn popen_rd/;
+sub RLIMITS () { qw(RLIMIT_CPU RLIMIT_CORE RLIMIT_DATA) }
 
 my $vfork_spawn = <<'VFORK_SPAWN';
 #include <sys/types.h>
@@ -202,7 +203,7 @@ sub spawn ($;$$) {
 	my $err = $opts->{2} || 2;
 	my $rlim = [];
 
-	foreach my $l (qw(RLIMIT_CPU RLIMIT_CORE RLIMIT_DATA)) {
+	foreach my $l (RLIMITS()) {
 		defined(my $v = $opts->{$l}) or next;
 		my ($soft, $hard);
 		if (ref($v)) {
-- 
EW


  parent reply	other threads:[~2019-03-12  4:00 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-12  4:00 [PATCH 00/13] support parsing cgitrc and spawning cgit Eric Wong
2019-03-12  4:00 ` [PATCH 01/13] git: add "commit_title" method Eric Wong
2019-03-12  4:00 ` [PATCH 02/13] viewvcs: preliminary support for showing non-blobs Eric Wong
2019-03-12  4:00 ` [PATCH 03/13] viewvcs: match 8000-byte lookup for git Eric Wong
2019-03-12  4:00 ` [PATCH 04/13] spawn: support RLIMIT_CPU, RLIMIT_DATA and RLIMIT_CORE Eric Wong
2019-03-12  4:00 ` [PATCH 05/13] support publicinbox.cgitrc directive Eric Wong
2019-03-12  4:00 ` [PATCH 06/13] githttpbackend: move more psgi.input handling into subroutine Eric Wong
2019-03-12  4:00 ` [PATCH 07/13] githttpbackend: check for other errors and relax CRLF check Eric Wong
2019-03-12  4:00 ` [PATCH 08/13] spawn: support absolute paths Eric Wong
2019-03-12  4:00 ` [PATCH 09/13] cgit: support running cgit as a standalone CGI Eric Wong
2019-03-12  4:00 ` [PATCH 10/13] www: wire up cgit as a 404 handler if cgitrc is configured Eric Wong
2019-03-12  4:00 ` Eric Wong [this message]
2019-03-12  4:00 ` [PATCH 12/13] cgit: use a dedicated named limiter Eric Wong
2019-03-12  4:00 ` [PATCH 13/13] spawn: require soft and hard vals for RLIMIT_* params Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://public-inbox.org/README

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190312040046.4619-12-e@80x24.org \
    --to=e@80x24.org \
    --cc=meta@public-inbox.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/public-inbox.git

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).