
From: Roland McGrath <roland@redhat.com>

Jeremy mentioned the aggravation of not being able to tell when your
processes are using up signal queue entries and hitting the
RLIMIT_SIGPENDING limit.  This patch adds a line to /proc/PID/status
showing how many queue items are in use, and allowed, for your uid.

I can certainly see the appeal of having a display of the number of queued
items specific to each process, and even the items within the process
broken down per signal number.  However, those are not things that are
directly counted, and ascertaining them requires iterating through the
queue.  This patch instead gives what can be readily determined in constant
time using the accounting already done.  I'm not sure something more
complex is warranted just to facilitate one particular debugging need. 
With this, you can see quickly that this particular problem has come up. 
Then examination of each process's SigPnd/ShdPnd lines ought to give you an
indication of which processes have any queued RT signals sitting around for
a long time, and you can then attack those programs directly, though there
is no way after the fact to determine how many queued signals with the same
number a given process has (short of killing it and seeing the usage drop).

Note you may still have a mystery if the leaking programs are not leaving
pending RT signals queued, but rather preallocating queue items via
timer_create.  That usage is not readily apparent in any /proc information.

Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/proc/array.c |    5 +++++
 1 files changed, 5 insertions(+)

diff -puN fs/proc/array.c~show-rlimit_sigpending-usage-in-proc-pid-status fs/proc/array.c
--- 25/fs/proc/array.c~show-rlimit_sigpending-usage-in-proc-pid-status	2005-03-07 20:41:53.000000000 -0800
+++ 25-akpm/fs/proc/array.c	2005-03-07 20:41:53.000000000 -0800
@@ -239,6 +239,8 @@ static inline char * task_sig(struct tas
 {
 	sigset_t pending, shpending, blocked, ignored, caught;
 	int num_threads = 0;
+	unsigned long qsize = 0;
+	unsigned long qlim = 0;
 
 	sigemptyset(&pending);
 	sigemptyset(&shpending);
@@ -255,11 +257,14 @@ static inline char * task_sig(struct tas
 		blocked = p->blocked;
 		collect_sigign_sigcatch(p, &ignored, &caught);
 		num_threads = atomic_read(&p->signal->count);
+		qsize = atomic_read(&p->user->sigpending);
+		qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
 		spin_unlock_irq(&p->sighand->siglock);
 	}
 	read_unlock(&tasklist_lock);
 
 	buffer += sprintf(buffer, "Threads:\t%d\n", num_threads);
+	buffer += sprintf(buffer, "SigQ:\t%lu/%lu\n", qsize, qlim);
 
 	/* render them all */
 	buffer = render_sigset_t("SigPnd:\t", &pending, buffer);
_
