diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 21 |
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; } |