Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c8e85b4f authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Linus Torvalds
Browse files

posix timers: sigqueue_free: don't free sigqueue if it is queued



Currently sigqueue_free() removes sigqueue from list, but doesn't cancel the
pending signal. This is not consistent, the task should either receive the
"full" signal along with siginfo_t, or it shouldn't receive the signal at all.

Change sigqueue_free() to clear SIGQUEUE_PREALLOC but leave sigqueue on list
if it is queued.

This is a user-visible change. If the signal is blocked, it stays queued
after sys_timer_delete() until unblocked with the "stale" si_code/si_value,
and of course it is still counted wrt RLIMIT_SIGPENDING which also limits
the number of posix timers.

Signed-off-by: default avatarOleg Nesterov <oleg@tv-sign.ru>
Cc: Austin Clements <amdragon+kernelbugzilla@mit.edu>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 84a88165
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -1240,17 +1240,21 @@ void sigqueue_free(struct sigqueue *q)

	BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
	/*
	 * If the signal is still pending remove it from the
	 * pending queue. We must hold ->siglock while testing
	 * q->list to serialize with collect_signal() or with
	 * We must hold ->siglock while testing q->list
	 * to serialize with collect_signal() or with
	 * __exit_signal()->flush_sigqueue().
	 */
	spin_lock_irqsave(lock, flags);
	q->flags &= ~SIGQUEUE_PREALLOC;
	/*
	 * If it is queued it will be freed when dequeued,
	 * like the "regular" sigqueue.
	 */
	if (!list_empty(&q->list))
		list_del_init(&q->list);
		q = NULL;
	spin_unlock_irqrestore(lock, flags);

	q->flags &= ~SIGQUEUE_PREALLOC;
	if (q)
		__sigqueue_free(q);
}