summaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index ff5ec0a8d..1aded9117 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -18,6 +18,7 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
@@ -35,8 +36,10 @@
static kmem_cache_t *signal_queue_cachep;
-void
-signals_init(void)
+static int nr_queued_signals;
+static int max_queued_signals = 1024;
+
+void __init signals_init(void)
{
signal_queue_cachep =
kmem_cache_create("signal_queue",
@@ -64,6 +67,7 @@ flush_signals(struct task_struct *t)
while (q) {
n = q->next;
kmem_cache_free(signal_queue_cachep, q);
+ nr_queued_signals--;
q = n;
}
}
@@ -160,7 +164,8 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid,
current->sigqueue_tail = pp;
*info = q->info;
kmem_cache_free(signal_queue_cachep,q);
-
+ nr_queued_signals--;
+
/* then see if this signal is still pending. */
q = *pp;
while (q) {
@@ -300,9 +305,14 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
make sure at least one signal gets delivered and don't
pass on the info struct. */
- struct signal_queue *q = (struct signal_queue *)
- kmem_cache_alloc(signal_queue_cachep, GFP_KERNEL);
+ struct signal_queue *q = 0;
+ if (nr_queued_signals < max_queued_signals) {
+ q = (struct signal_queue *)
+ kmem_cache_alloc(signal_queue_cachep, GFP_KERNEL);
+ nr_queued_signals++;
+ }
+
if (q) {
q->next = NULL;
*t->sigqueue_tail = q;
@@ -825,6 +835,7 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
else {
*pp = q->next;
kmem_cache_free(signal_queue_cachep, q);
+ nr_queued_signals--;
}
q = *pp;
}