Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Jan 2012 22:31:45 +0200
From:      Mikolaj Golub <trociny@freebsd.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Cc:        Andrey Zonov <andrey@zonov.org>, Kostik Belousov <kib@FreeBSD.org>
Subject:   Re: svn commit: r230470 - in head/sys: kern sys
Message-ID:  <86d3abtr66.fsf@kopusha.home.net>
In-Reply-To: <201201222025.q0MKP0Ix091451@svn.freebsd.org> (Mikolaj Golub's message of "Sun, 22 Jan 2012 20:25:00 %2B0000 (UTC)")
References:  <201201222025.q0MKP0Ix091451@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
--=-=-=


On Sun, 22 Jan 2012 20:25:00 +0000 (UTC) Mikolaj Golub wrote:

 MG> Author: trociny
 MG> Date: Sun Jan 22 20:25:00 2012
 MG> New Revision: 230470
 MG> URL: http://svn.freebsd.org/changeset/base/230470

 MG> Log:
 MG>   Change kern.proc.rlimit sysctl to:
 MG>   
 MG>   - retrive only one, specified limit for a process, not the whole
 MG>     array, as it was previously (the sysctl has been added recently and
 MG>     has not been backported to stable yet, so this change is ok);
 MG>   
 MG>   - allow to set a resource limit for another process.
 MG>   
 MG>   Submitted by:        Andrey Zonov <andrey at zonov.org>
 MG>   Discussed with:        kib
 MG>   Reviewed by:        kib
 MG>   MFC after:        2 weeks

Andrey has also been working on the patch for limits(1), which allows
to view/set limits for another process:

- If '-P <pid>' without the list of limits is specified it returns the
limits for this process.

- If '-P <pid>' with the list of limits is specified it changes these
limits for the process.

- If '-P <pid>' with list of limits is specified but also -a option is
present it outputs all limits for the process updated by the command
line setting. So if one want, for example, to set for a current shell
all limits as they are for a process <pid>, but core dump is disabled,
it could run:

eval `limits -P <pid> -aBec 0`

The latest version of the patch is attached. I am going to commit it
if there are no objections or suggestions.

-- 
Mikolaj Golub


--=-=-=
Content-Type: text/x-patch
Content-Disposition: inline; filename=limits.patch

Index: usr.bin/limits/limits.1
===================================================================
--- usr.bin/limits/limits.1	(revision 230394)
+++ usr.bin/limits/limits.1	(working copy)
@@ -19,7 +19,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd April 10, 2011
+.Dd January 18, 2011
 .Dt LIMITS 1
 .Os
 .Sh NAME
@@ -28,11 +28,13 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl C Ar class | Fl U Ar user
+.Op Fl P Ar pid
 .Op Fl SHB
 .Op Fl ea
 .Op Fl bcdflmnstuvpw Op Ar val
 .Nm
 .Op Fl C Ar class | Fl U Ar user
+.Op Fl P Ar pid
 .Op Fl SHB
 .Op Fl bcdflmnstuvpw Op Ar val
 .Op Fl E
@@ -143,6 +145,9 @@ for the
 class are used, if it exists, or the
 .Dq Li root
 class if the user is a superuser account.
+.It Fl P Ar pid
+Select or set limits for the process identified by the
+.Ar pid .
 .It Fl S
 Select display or setting of
 .Dq soft
Index: usr.bin/limits/limits.c
===================================================================
--- usr.bin/limits/limits.c	(revision 230394)
+++ usr.bin/limits/limits.c	(working copy)
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/sysctl.h>
 #include <sys/param.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -249,6 +250,8 @@ static void usage(void);
 static int getshelltype(void);
 static void print_limit(rlim_t limit, unsigned divisor, const char *inf,
 			const char *pfx, const char *sfx, const char *which);
+static void getrlimit_proc(pid_t pid, int resource, struct rlimit *rlp);
+static void setrlimit_proc(pid_t pid, int resource, const struct rlimit *rlp);
 extern char **environ;
 
 static const char rcs_string[] = RCS_STRING;
@@ -262,24 +265,24 @@ main(int argc, char *argv[])
     int rcswhich, shelltype;
     int i, num_limits = 0;
     int ch, doeval = 0, doall = 0;
-    int rtrn;
+    int rtrn, setproc;
     login_cap_t * lc = NULL;
     enum { ANY=0, SOFT=1, HARD=2, BOTH=3, DISPLAYONLY=4 } type = ANY;
     enum { RCSUNKNOWN=0, RCSSET=1, RCSSEL=2 } todo = RCSUNKNOWN;
     int which_limits[RLIM_NLIMITS];
     rlim_t set_limits[RLIM_NLIMITS];
     struct rlimit limits[RLIM_NLIMITS];
+    pid_t pid;
 
     /* init resource tables */
     for (i = 0; i < RLIM_NLIMITS; i++) {
 	which_limits[i] = 0; /* Don't set/display any */
 	set_limits[i] = RLIM_INFINITY;
-	/* Get current resource values */
-	getrlimit(i, &limits[i]);
     }
 
+    pid = -1;
     optarg = NULL;
-    while ((ch = getopt(argc, argv, ":EeC:U:BSHab:c:d:f:l:m:n:s:t:u:v:p:w:")) != -1) {
+    while ((ch = getopt(argc, argv, ":EeC:U:BSHP:ab:c:d:f:l:m:n:s:t:u:v:p:w:")) != -1) {
 	switch(ch) {
 	case 'a':
 	    doall = 1;
@@ -312,6 +315,12 @@ main(int argc, char *argv[])
 	case 'B':
 	    type = SOFT|HARD;
 	    break;
+	case 'P':
+	    if (!isdigit(*optarg) || (pid = atoi(optarg)) < 0) {
+		warnx("invalid pid `%s'", optarg);
+		usage();
+	    }
+	    break;
 	default:
 	case ':': /* Without arg */
 	    if ((p = strchr(rcs_string, optopt)) != NULL) {
@@ -335,6 +344,30 @@ main(int argc, char *argv[])
 	optarg = NULL;
     }
 
+    if (pid != -1) {
+	if (cls != NULL) {
+	    warnx("-C cannot be used with -P option");
+	    usage();
+	}
+	if (pwd != NULL) {
+	    warnx("-U cannot be used with -P option");
+	    usage();
+	}
+    }
+
+    /* Get current resource values */
+    setproc = 0;
+    for (i = 0; i < RLIM_NLIMITS; i++) {
+	if (pid == -1) {
+	    getrlimit(i, &limits[i]);
+	} else if (doall || num_limits == 0) {
+	    getrlimit_proc(pid, i, &limits[i]);
+	} else if (which_limits[i] != 0) {
+	    getrlimit_proc(pid, i, &limits[i]);
+	    setproc = 1;
+	}
+    }
+
     /* If user was specified, get class from that */
     if (pwd != NULL)
 	lc = login_getpwclass(pwd);
@@ -414,6 +447,10 @@ main(int argc, char *argv[])
 	    warnx("-e cannot be used with `cmd' option");
 	    usage();
 	}
+	if (pid != -1) {
+	    warnx("-P cannot be used with `cmd' option");
+	    usage();
+	}
 
 	login_close(lc);
 
@@ -440,6 +477,14 @@ main(int argc, char *argv[])
 	err(1, "%s", *argv);
     }
 
+    if (setproc) {
+	for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) {
+	    if (which_limits[rcswhich] != 0)
+		setrlimit_proc(pid, rcswhich, &limits[rcswhich]);
+	}
+	exit(EXIT_SUCCESS);
+    }
+
     shelltype = doeval ? getshelltype() : SH_NONE;
 
     if (type == ANY) /* Default to soft limits */
@@ -493,7 +538,8 @@ static void
 usage(void)
 {
     (void)fprintf(stderr,
-"usage: limits [-C class|-U user] [-eaSHBE] [-bcdflmnstuvpw [val]] [[name=val ...] cmd]\n");
+	"usage: limits [-C class|-U user|-P pid] [-eaSHBE] "
+	"[-bcdflmnstuvpw [val]] [[name=val ...] cmd]\n");
     exit(EXIT_FAILURE);
 }
 
@@ -677,3 +723,38 @@ getshelltype(void)
     return SH_SH;
 }
 
+static void
+getrlimit_proc(pid_t pid, int resource, struct rlimit *rlp)
+{
+    int error;
+    int name[5];
+    size_t len;
+
+    name[0] = CTL_KERN;
+    name[1] = KERN_PROC;
+    name[2] = KERN_PROC_RLIMIT;
+    name[3] = pid;
+    name[4] = resource;
+    len = sizeof(*rlp);
+    error = sysctl(name, 5, rlp, &len, NULL, 0);
+    if (error == -1)
+	err(EXIT_FAILURE, "sysctl: kern.proc.rlimit: %d", pid);
+    if (len != sizeof(*rlp))
+	errx(EXIT_FAILURE, "sysctl() returns wrong size");
+}
+
+static void
+setrlimit_proc(pid_t pid, int resource, const struct rlimit *rlp)
+{
+    int error;
+    int name[5];
+
+    name[0] = CTL_KERN;
+    name[1] = KERN_PROC;
+    name[2] = KERN_PROC_RLIMIT;
+    name[3] = pid;
+    name[4] = resource;
+    error = sysctl(name, 5, NULL, 0, rlp, sizeof(*rlp));
+    if (error == -1)
+	err(EXIT_FAILURE, "sysctl: kern.proc.rlimit: %d", pid);
+}

--=-=-=--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?86d3abtr66.fsf>