aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-09-09 17:44:16 +0300
committerSergey Poznyakoff <gray@gnu.org>2020-09-09 17:44:16 +0300
commitfb0f0c9767831a373ab6a46781fad52987191c12 (patch)
tree631b3b88470d69bc2a11fbb0a739791287dbd4ac
parentaeef348db666ab537054a6ab48a75586fc7c6733 (diff)
downloadgenrc-fb0f0c9767831a373ab6a46781fad52987191c12.tar.gz
genrc-fb0f0c9767831a373ab6a46781fad52987191c12.tar.bz2
New option to limit the runtime resource usage.
* src/genrc.c: Implement the --limit (-l) option. * NEWS: Update. * src/genrc.8: Document the --limit option.
-rw-r--r--NEWS31
-rw-r--r--src/genrc.842
-rw-r--r--src/genrc.c103
3 files changed, 172 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index 3a98ba7..153fad6 100644
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,14 @@ See the end of file for copying conditions.
Please send genrc bug reports to <gray@gnu.org> or <gray@gnu.org.ua>
-* New options
+* Verbose diagnostics
+
+Verbose diagnostics is enabled by the -v,--verbose option.
+
+* Shell selection
+
+By default, the program is started using "/bin/sh -c". Two options
+are provided to alter this behavior:
-s, --shell=SHELL
Use SHELL to start the program. Default is /bin/sh.
@@ -13,8 +20,9 @@ Please send genrc bug reports to <gray@gnu.org> or <gray@gnu.org.ua>
In sentinel mode, run the command directly via exec(3), instead
of via the shell.
- -v,--verbose
- Print verbose diagnostics.
+* Syslog
+
+In sentinel mode, the syslog facility and tag can be changed:
--log-facility=F
Use syslog facility F instead of the default "daemon".
@@ -24,6 +32,23 @@ Please send genrc bug reports to <gray@gnu.org> or <gray@gnu.org.ua>
Use syslog tag S instead of the program name.
(equivalent environment variable - GENRC_LOG_TAG)
+* Runtime resource limits
+
+The --limit (-l) option is provided to control the resource usage.
+Its argument is a resource designator followed by the limit value
+for that resource. Resource designators are:
+
+ c Core file size (KB).
+ d Data size (KB).
+ f File size (KB).
+ l Locked-in-memory address space (KB).
+ m Resident set size (KB).
+ n Number of open files.
+ p Process priority (nice value), -20..20.
+ s Stack size (KB).
+ t CPU time (seconds).
+ u Number of subprocesses.
+ v Virtual memory size (KB).
Version 1.1, 2018-05-20
diff --git a/src/genrc.8 b/src/genrc.8
index 49d8127..c4715da 100644
--- a/src/genrc.8
+++ b/src/genrc.8
@@ -25,6 +25,7 @@ genrc \- generic system initialization script helper
[\fB\-P\fR \fISOURCE\fR]\
[\fB\-c\fR \fICOMMAND\fR]\
[\fB\-g\fR \fIGROUP\fR[,\fIGROUP\fR...]]\
+ [\fB\-l\fR \fILIMIT\fR]\
[\fB\-p\fR \fIPROGRAM\fR]\
[\fB\-s\fR \fISHELL\fR]\
[\fB\-t\fR \fISECONDS\fR]\
@@ -36,6 +37,7 @@ genrc \- generic system initialization script helper
[\fB\-\-help\fR]\
[\fB\-\-log\-facility=\fIFACILITY\fR]\
[\fB\-\-log\-tag=\fITAG\fR]\
+ [\fB\-\-limit=\fILIMIT\fR]\
[\fB\-\-no\-reload\fR]\
[\fB\-\-pid\-from=\fISOURCE\fR]\
[\fB\-\-pidfile=\fIPIDFILE\fR]\
@@ -214,6 +216,46 @@ notation is used, the groups must exist in the system group database.
See also the \fB\-\-user\fR option.
.TP
+\fB\-l\fR, \fB\-\-limit=\fILIM\fR
+Set resource limit. \fILIM\fR is a resource letter followed by
+a value. Resource letters are:
+.RS
+.TP
+.B c
+Core file size (KB).
+.TP
+.B d
+Data size (KB).
+.TP
+.B f
+File size (KB).
+.TP
+.B l
+Locked-in-memory address space (KB).
+.TP
+.B m
+Resident set size (KB).
+.TP
+.B n
+Number of open files.
+.TP
+.B p
+Process priority (nice value), -20..20.
+.TP
+.B s
+Stack size (KB).
+.TP
+.B t
+CPU time (seconds).
+.TP
+.B u
+Number of subprocesses.
+.TP
+.B v
+Virtual memory size (KB).
+.RE
+.TP
+.TP
\fB\-\-log\-facility=\fIFACILITY\fR
Selects \fBsyslog\fR facility for use in sentinel mode. Valid arguments are
.BR auth ,
diff --git a/src/genrc.c b/src/genrc.c
index 5f66552..04845d0 100644
--- a/src/genrc.c
+++ b/src/genrc.c
@@ -7,6 +7,7 @@ There is NO WARRANTY, to the extent permitted by law.
#include "genrc.h"
#include <syslog.h>
#include <sys/ioctl.h>
+#include <sys/resource.h>
char *genrc_command;
char *genrc_program;
@@ -58,6 +59,7 @@ struct option longopts[] = {
{ "restart-on-signal", required_argument, 0, OPT_RESTART_ON_SIGNAL },
{ "log-facility", required_argument, 0, OPT_LOG_FACILITY },
{ "log-tag", required_argument, 0, OPT_LOG_TAG },
+ { "limit", required_argument, 0, 'l' },
{ NULL }
};
char shortopts[2*sizeof(longopts)/sizeof(longopts[0])];
@@ -212,11 +214,24 @@ char const *help_msg[] = {
" Otherwise, if COMMAND is set, but PROGRAM is not, PROGRAM is set to the",
" first word (in the shell sense) in COMMAND.",
"",
- "Runtime privileges:",
+ "Runtime privileges and limits:",
"",
" -u, --user=NAME run with this user privileges",
" -g, --group=GROUP[,GROUP...]]",
" run with this group(s) privileges",
+ " -l, --limit=LIM set resource limit; LIM is a resource letter",
+ " followed by the resource value; resource letters are:",
+ " c core file size (KB)",
+ " d data size (KB)",
+ " f file size (KB)",
+ " l locked-in-memory address space (KB)",
+ " m resident set size (KB)",
+ " n number of open files",
+ " p process priority -20..20",
+ " s stack size (KB)",
+ " t CPU time (seconds)",
+ " u number of subprocesses",
+ " v virtual memory (KB)",
"",
"Additional configuration:",
"",
@@ -318,6 +333,7 @@ char const *usage_msg[] = {
"[-P SOURCE]",
"[-c COMMAND]",
"[-g GROUP[,GROUP...]]",
+ "[-l LIM]",
"[-p PROGRAM]",
"[-s SHELL]",
"[-t SECONDS]",
@@ -325,6 +341,7 @@ char const *usage_msg[] = {
"[--command=COMMAND]",
"[--group GROUP[,GROUP...]]",
"[--help]",
+ "[--limit=LIM]",
"[--log-facility=FACILITY]",
"[--log-tag=TAG]",
"[--no-reload]",
@@ -370,6 +387,84 @@ screen_width(void)
return ws.ws_col;
}
+static struct {
+ int letter;
+ int resource;
+ int is_set;
+ long val;
+} resource_tab[] = {
+ { 'c', RLIMIT_CORE },
+ { 'd', RLIMIT_DATA },
+ { 'f', RLIMIT_FSIZE },
+ { 'l', RLIMIT_MEMLOCK },
+ { 'm', RLIMIT_RSS },
+ { 'n', RLIMIT_NOFILE },
+ { 's', RLIMIT_STACK },
+ { 't', RLIMIT_CPU },
+ { 'u', RLIMIT_NPROC },
+ { 'v', RLIMIT_AS },
+ { 'p', 0 }
+};
+
+static int
+find_resource(int letter)
+{
+ int i;
+ for (i = 0; i < sizeof(resource_tab)/sizeof(resource_tab[0]); i++)
+ if (letter == resource_tab[i].letter)
+ return resource_tab[i].resource;
+ return -1;
+}
+
+void
+set_limit(char *arg)
+{
+ int r;
+ unsigned long v;
+ char *p;
+ struct rlimit rlim;
+
+ if ((r = find_resource(arg[0])) == -1) {
+ usage_error("%s: unrecognized resource code", arg);
+ }
+ if ((v = strtoul(arg + 1, &p, 10)) == ULONG_MAX && errno == ERANGE) {
+ usage_error("%s: resource value out of range", arg);
+ }
+ if (*p) {
+ usage_error("%s: value is not a number (stopped at %s)",
+ arg, p);
+ }
+
+ v *= 1024;
+ rlim.rlim_cur = v;
+ rlim.rlim_max = v;
+ if (setrlimit(r, &rlim))
+ genrc_error("%s: failed to set limit: %s", arg,
+ strerror(errno));
+}
+
+void
+set_nice(char *arg)
+{
+ long v;
+ char *p;
+
+ if ((((v = strtol(arg + 1, &p, 10)) == LONG_MAX || v == LONG_MIN)
+ && errno == ERANGE) ||
+ v < -20 ||
+ v > 20) {
+ usage_error("%s: resource value out of range", arg);
+ }
+ if (*p) {
+ usage_error("%s: value is not a number (stopped at %s)",
+ arg, p);
+ }
+ if (setpriority (PRIO_PROCESS, 0, v)) {
+ usage_error("failed to set process priority: %s",
+ strerror(errno));
+ }
+}
+
void
usage(void)
{
@@ -503,6 +598,12 @@ main(int argc, char **argv)
case 'e':
genrc_shell = NULL;
break;
+ case 'l':
+ if (optarg[0] == 'p')
+ set_nice(optarg+1);
+ else
+ set_limit(optarg);
+ break;
case 's':
if (strcmp(optarg, "no") == 0
|| strcmp(optarg, "none") == 0)

Return to:

Send suggestions and report system problems to the System administrator.