bin/161257: procstat(1): procstat should grow a -l flag to display resource limits

Mikolaj Golub trociny at freebsd.org
Sat Nov 5 13:20:16 UTC 2011


The following reply was made to PR bin/161257; it has been noted by GNATS.

From: Mikolaj Golub <trociny at freebsd.org>
To: John Baldwin <jhb at FreeBSD.org>
Cc: bug-followup at FreeBSD.org, Kostik Belousov <kib at FreeBSD.org>, Robert Watson <rwatson at freebsd.org>
Subject: Re: bin/161257: procstat(1): procstat should grow a -l flag to display resource limits
Date: Sat, 05 Nov 2011 14:45:03 +0200

 --=-=-=
 
 Hi,
 
 Here is the patch that does 'procstat -l'. 
 
 Note, I had to change rlimit_ident[] from char * to const char * to make
 procstat compile without warnings.
 
 -- 
 Mikolaj Golub
 
 
 --=-=-=
 Content-Type: text/x-patch
 Content-Disposition: attachment; filename=rlimit.patch
 
 diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
 index 998e7ca..77cbd4e 100644
 --- a/sys/kern/kern_proc.c
 +++ b/sys/kern/kern_proc.c
 @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/mutex.h>
  #include <sys/proc.h>
  #include <sys/refcount.h>
 +#include <sys/resourcevar.h>
  #include <sys/sbuf.h>
  #include <sys/sysent.h>
  #include <sys/sched.h>
 @@ -1989,6 +1990,38 @@ sysctl_kern_proc_groups(SYSCTL_HANDLER_ARGS)
  	return (error);
  }
  
 +/*
 + * This sysctl allows a process to retrieve the resource limits for
 + * another process.
 + */
 +static int
 +sysctl_kern_proc_rlimit(SYSCTL_HANDLER_ARGS)
 +{
 +	int *name = (int*) arg1;
 +	u_int namelen = arg2;
 +        struct plimit *limp;
 +	struct proc *p;
 +	int error = 0;
 +
 +	if (namelen != 1)
 +		return (EINVAL);
 +
 +	p = pfind((pid_t)name[0]);
 +	if (p == NULL)
 +		return (ESRCH);
 +
 +	if ((error = p_cansee(curthread, p)) != 0) {
 +		PROC_UNLOCK(p);
 +		return (error);
 +	}
 +
 +	limp = lim_hold(p->p_limit);
 +	PROC_UNLOCK(p);
 +	error = SYSCTL_OUT(req, limp->pl_rlimit, sizeof(limp->pl_rlimit));
 +        lim_free(limp);
 +        return (error);
 +}
 +
  SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD,  0, "Process table");
  
  SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT|
 @@ -2076,3 +2109,6 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC_KSTACK, kstack, CTLFLAG_RD |
  
  static SYSCTL_NODE(_kern_proc, KERN_PROC_GROUPS, groups, CTLFLAG_RD |
  	CTLFLAG_MPSAFE, sysctl_kern_proc_groups, "Process groups");
 +
 +static SYSCTL_NODE(_kern_proc, KERN_PROC_RLIMIT, rlimit, CTLFLAG_RD |
 +	CTLFLAG_MPSAFE, sysctl_kern_proc_rlimit, "Process resource limits");
 diff --git a/sys/sys/resource.h b/sys/sys/resource.h
 index 7d0b4ee..c5e912bd 100644
 --- a/sys/sys/resource.h
 +++ b/sys/sys/resource.h
 @@ -108,7 +108,7 @@ struct rusage {
   */
  
  #ifdef _RLIMIT_IDENT
 -static char *rlimit_ident[RLIM_NLIMITS] = {
 +static const char *rlimit_ident[RLIM_NLIMITS] = {
  	"cpu",
  	"fsize",
  	"data",
 diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
 index 1e879f5..98b253b 100644
 --- a/sys/sys/sysctl.h
 +++ b/sys/sys/sysctl.h
 @@ -559,6 +559,7 @@ SYSCTL_ALLOWED_TYPES(UINT64, uint64_t *a; unsigned long long *b; );
  #define	KERN_PROC_VMMAP		32	/* VM map entries for process */
  #define	KERN_PROC_FILEDESC	33	/* File descriptors for process */
  #define	KERN_PROC_GROUPS	34	/* process groups */
 +#define	KERN_PROC_RLIMIT	35	/* process resource limits */
  
  /*
   * KERN_IPC identifiers
 diff --git a/usr.bin/procstat/Makefile b/usr.bin/procstat/Makefile
 index e8e35ed..5aa683c 100644
 --- a/usr.bin/procstat/Makefile
 +++ b/usr.bin/procstat/Makefile
 @@ -9,6 +9,7 @@ SRCS=	procstat.c		\
  	procstat_cred.c		\
  	procstat_files.c	\
  	procstat_kstack.c	\
 +	procstat_rlimit.c	\
  	procstat_sigs.c		\
  	procstat_threads.c	\
  	procstat_vm.c
 diff --git a/usr.bin/procstat/procstat.1 b/usr.bin/procstat/procstat.1
 index 35fab1f..1b3b8c1 100644
 --- a/usr.bin/procstat/procstat.1
 +++ b/usr.bin/procstat/procstat.1
 @@ -25,7 +25,7 @@
  .\"
  .\" $FreeBSD$
  .\"
 -.Dd August 14, 2011
 +.Dd November 5, 2011
  .Dt PROCSTAT 1
  .Os
  .Sh NAME
 @@ -67,6 +67,8 @@ Display the stacks of kernel threads in the process, excluding stacks of
  threads currently running on a CPU and threads with stacks swapped to disk.
  If the flag is repeated, function offsets as well as function names are
  printed.
 +.It Fl l
 +Display resource limits for the process.
  .It Fl s
  Display security credential information for the process.
  .It Fl t
 diff --git a/usr.bin/procstat/procstat.c b/usr.bin/procstat/procstat.c
 index 97ff879..c79bb39 100644
 --- a/usr.bin/procstat/procstat.c
 +++ b/usr.bin/procstat/procstat.c
 @@ -39,7 +39,8 @@
  
  #include "procstat.h"
  
 -static int aflag, bflag, cflag, fflag, iflag, jflag, kflag, sflag, tflag, vflag;
 +static int aflag, bflag, cflag, fflag, iflag, jflag, kflag, lflag, sflag, tflag;
 +static int vflag;
  int	hflag, nflag, Cflag;
  
  static void
 @@ -47,7 +48,7 @@ usage(void)
  {
  
  	fprintf(stderr, "usage: procstat [-h] [-C] [-M core] [-N system] "
 -	    "[-w interval] [-b | -c | -f | -i | -j | -k | -s | -t | -v]\n");
 +	    "[-w interval] [-b | -c | -f | -i | -j | -k | -l | -s | -t | -v]\n");
  	fprintf(stderr, "                [-a | pid ...]\n");
  	exit(EX_USAGE);
  }
 @@ -68,6 +69,8 @@ procstat(struct procstat *prstat, struct kinfo_proc *kipp)
  		procstat_threads_sigs(prstat, kipp);
  	else if (kflag)
  		procstat_kstack(kipp, kflag);
 +	else if (lflag)
 +		procstat_rlimit(kipp);
  	else if (sflag)
  		procstat_cred(kipp);
  	else if (tflag)
 @@ -117,7 +120,7 @@ main(int argc, char *argv[])
  
  	interval = 0;
  	memf = nlistf = NULL;
 -	while ((ch = getopt(argc, argv, "CN:M:abcfijkhstvw:")) != -1) {
 +	while ((ch = getopt(argc, argv, "CN:M:abcfijklhstvw:")) != -1) {
  		switch (ch) {
  		case 'C':
  			Cflag++;
 @@ -157,6 +160,10 @@ main(int argc, char *argv[])
  			kflag++;
  			break;
  
 +		case 'l':
 +			lflag++;
 +			break;
 +
  		case 'n':
  			nflag++;
  			break;
 @@ -196,7 +203,8 @@ main(int argc, char *argv[])
  	argv += optind;
  
  	/* We require that either 0 or 1 mode flags be set. */
 -	tmp = bflag + cflag + fflag + (kflag ? 1 : 0) + sflag + tflag + vflag;
 +	tmp = bflag + cflag + fflag + (kflag ? 1 : 0) + lflag + sflag + tflag +
 +	    vflag;
  	if (!(tmp == 0 || tmp == 1))
  		usage();
  
 diff --git a/usr.bin/procstat/procstat.h b/usr.bin/procstat/procstat.h
 index 71e3ca7..5994feb 100644
 --- a/usr.bin/procstat/procstat.h
 +++ b/usr.bin/procstat/procstat.h
 @@ -40,6 +40,7 @@ void	procstat_bin(struct kinfo_proc *kipp);
  void	procstat_cred(struct kinfo_proc *kipp);
  void	procstat_files(struct procstat *prstat, struct kinfo_proc *kipp);
  void	procstat_kstack(struct kinfo_proc *kipp, int kflag);
 +void	procstat_rlimit(struct kinfo_proc *kipp);
  void	procstat_sigs(struct procstat *prstat, struct kinfo_proc *kipp);
  void	procstat_threads(struct kinfo_proc *kipp);
  void	procstat_threads_sigs(struct procstat *prstat, struct kinfo_proc *kipp);
 diff --git a/usr.bin/procstat/procstat_rlimit.c b/usr.bin/procstat/procstat_rlimit.c
 new file mode 100644
 index 0000000..59d2323
 --- /dev/null
 +++ b/usr.bin/procstat/procstat_rlimit.c
 @@ -0,0 +1,83 @@
 +/*-
 + * Copyright (c) 2011 Mikolaj Golub
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. Redistributions in binary form must reproduce the above copyright
 + *    notice, this list of conditions and the following disclaimer in the
 + *    documentation and/or other materials provided with the distribution.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + */
 +
 +#include <sys/param.h>
 +#include <sys/time.h>
 +#define _RLIMIT_IDENT
 +#include <sys/resourcevar.h>
 +#include <sys/sysctl.h>
 +#include <sys/user.h>
 +
 +#include <err.h>
 +#include <errno.h>
 +#include <libprocstat.h>
 +#include <limits.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +
 +#include "procstat.h"
 +
 +static struct rlimit rlimit[RLIM_NLIMITS];
 +
 +void
 +procstat_rlimit(struct kinfo_proc *kipp)
 +{
 +	int error, i, name[4];
 +	size_t len;
 +
 +	if (!hflag)
 +		printf("%5s %-16s %-53s\n", "PID", "COMM", "RLIMIT");
 +
 +	name[0] = CTL_KERN;
 +	name[1] = KERN_PROC;
 +	name[2] = KERN_PROC_RLIMIT;
 +	name[3] = kipp->ki_pid;
 +	len = sizeof(rlimit);
 +	error = sysctl(name, 4, rlimit, &len, NULL, 0);
 +	if (error < 0 && errno != ESRCH) {
 +		warn("sysctl: kern.proc.rlimit: %d", kipp->ki_pid);
 +		return;
 +	}
 +	if (error < 0)
 +		return;
 +
 +	printf("%5d %-16s", kipp->ki_pid, kipp->ki_comm);
 +	if (len != sizeof(rlimit)) {
 +		printf("-\n");
 +		return;
 +	}
 +	for (i = 0; i < RLIM_NLIMITS; i++) {
 +		printf(" %s:%jd/%jd", rlimit_ident[i],
 +		    rlimit[i].rlim_cur == RLIM_INFINITY ?
 +		    -1 : rlimit[i].rlim_cur,
 +		    rlimit[i].rlim_max == RLIM_INFINITY ?
 +		    -1 : rlimit[i].rlim_max);
 +        }
 +	printf("\n");
 +}
 
 --=-=-=--


More information about the freebsd-bugs mailing list