|
@@ -1300,20 +1300,19 @@ struct sigqueue *sigqueue_alloc(void)
|
|
|
void sigqueue_free(struct sigqueue *q)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
+ spinlock_t *lock = ¤t->sighand->siglock;
|
|
|
+
|
|
|
BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
|
|
|
/*
|
|
|
* If the signal is still pending remove it from the
|
|
|
- * pending queue.
|
|
|
+ * pending queue. We must hold ->siglock while testing
|
|
|
+ * q->list to serialize with collect_signal().
|
|
|
*/
|
|
|
- if (unlikely(!list_empty(&q->list))) {
|
|
|
- spinlock_t *lock = ¤t->sighand->siglock;
|
|
|
- read_lock(&tasklist_lock);
|
|
|
- spin_lock_irqsave(lock, flags);
|
|
|
- if (!list_empty(&q->list))
|
|
|
- list_del_init(&q->list);
|
|
|
- spin_unlock_irqrestore(lock, flags);
|
|
|
- read_unlock(&tasklist_lock);
|
|
|
- }
|
|
|
+ spin_lock_irqsave(lock, flags);
|
|
|
+ if (!list_empty(&q->list))
|
|
|
+ list_del_init(&q->list);
|
|
|
+ spin_unlock_irqrestore(lock, flags);
|
|
|
+
|
|
|
q->flags &= ~SIGQUEUE_PREALLOC;
|
|
|
__sigqueue_free(q);
|
|
|
}
|