diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 19 |
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) | |||
1300 | void sigqueue_free(struct sigqueue *q) | 1300 | void sigqueue_free(struct sigqueue *q) |
1301 | { | 1301 | { |
1302 | unsigned long flags; | 1302 | unsigned long flags; |
1303 | spinlock_t *lock = ¤t->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 = ¤t->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 | } |