aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index ad63109e413c..3169bed0b4d0 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1300,20 +1300,19 @@ struct sigqueue *sigqueue_alloc(void)
1300void sigqueue_free(struct sigqueue *q) 1300void sigqueue_free(struct sigqueue *q)
1301{ 1301{
1302 unsigned long flags; 1302 unsigned long flags;
1303 spinlock_t *lock = &current->sighand->siglock;
1304
1303 BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); 1305 BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
1304 /* 1306 /*
1305 * If the signal is still pending remove it from the 1307 * If the signal is still pending remove it from the
1306 * pending queue. 1308 * pending queue. We must hold ->siglock while testing
1309 * q->list to serialize with collect_signal().
1307 */ 1310 */
1308 if (unlikely(!list_empty(&q->list))) { 1311 spin_lock_irqsave(lock, flags);
1309 spinlock_t *lock = &current->sighand->siglock; 1312 if (!list_empty(&q->list))
1310 read_lock(&tasklist_lock); 1313 list_del_init(&q->list);
1311 spin_lock_irqsave(lock, flags); 1314 spin_unlock_irqrestore(lock, flags);
1312 if (!list_empty(&q->list)) 1315
1313 list_del_init(&q->list);
1314 spin_unlock_irqrestore(lock, flags);
1315 read_unlock(&tasklist_lock);
1316 }
1317 q->flags &= ~SIGQUEUE_PREALLOC; 1316 q->flags &= ~SIGQUEUE_PREALLOC;
1318 __sigqueue_free(q); 1317 __sigqueue_free(q);
1319} 1318}