From: Frederic Weisbecker <frederic@kernel.org>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: LKML <linux-kernel@vger.kernel.org>,
Anna-Maria Behnsen <anna-maria@linutronix.de>,
John Stultz <jstultz@google.com>,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@kernel.org>, Stephen Boyd <sboyd@kernel.org>,
Eric Biederman <ebiederm@xmission.com>,
Oleg Nesterov <oleg@redhat.com>
Subject: Re: [patch v6.1 17/20] signal: Queue ignored posixtimers on ignore list
Date: Mon, 4 Nov 2024 12:42:16 +0100 [thread overview]
Message-ID: <ZyizGM4-3FmPDtGj@localhost.localdomain> (raw)
In-Reply-To: <8734k9qrcr.ffs@tglx>
Le Sat, Nov 02, 2024 at 10:05:08PM +0100, Thomas Gleixner a écrit :
> Queue posixtimers which have their signal ignored on the ignored list:
>
> 1) When the timer fires and the signal has SIG_IGN set
>
> 2) When SIG_IGN is installed via sigaction() and a timer signal
> is already queued
>
> This completes the SIG_IGN handling and such timers are not longer self
> rearmed which avoids pointless wakeups.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> ---
> V6.1: Handle oneshot timer expiry or transitioning from periodic to
> oneshot after a rearming correctly. - Frederic
> ---
> kernel/signal.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 65 insertions(+), 5 deletions(-)
> ---
>
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -731,6 +731,16 @@ void signal_wake_up_state(struct task_st
> kick_process(t);
> }
>
> +static inline void posixtimer_sig_ignore(struct task_struct *tsk, struct sigqueue *q);
> +
> +static void sigqueue_free_ignored(struct task_struct *tsk, struct sigqueue *q)
> +{
> + if (likely(!(q->flags & SIGQUEUE_PREALLOC) || q->info.si_code != SI_TIMER))
> + __sigqueue_free(q);
> + else
> + posixtimer_sig_ignore(tsk, q);
> +}
> +
> /* Remove signals in mask from the pending set and queue. */
> static void flush_sigqueue_mask(struct task_struct *p, sigset_t *mask, struct sigpending *s)
> {
> @@ -747,7 +757,7 @@ static void flush_sigqueue_mask(struct t
> list_for_each_entry_safe(q, n, &s->list, list) {
> if (sigismember(mask, q->info.si_signo)) {
> list_del_init(&q->list);
> - __sigqueue_free(q);
> + sigqueue_free_ignored(p, q);
> }
> }
> }
> @@ -1964,7 +1974,7 @@ int posixtimer_send_sigqueue(struct k_it
> int sig = q->info.si_signo;
> struct task_struct *t;
> unsigned long flags;
> - int ret, result;
> + int result;
>
> guard(rcu)();
>
> @@ -1981,13 +1991,48 @@ int posixtimer_send_sigqueue(struct k_it
> */
> tmr->it_sigqueue_seq = tmr->it_signal_seq;
>
> - ret = 1; /* the signal is ignored */
> if (!prepare_signal(sig, t, false)) {
> result = TRACE_SIGNAL_IGNORED;
> +
> + /* Paranoia check. Try to survive. */
> + if (WARN_ON_ONCE(!list_empty(&q->list)))
> + goto out;
> +
> + /* Periodic timers with SIG_IGN are queued on the ignored list */
> + if (tmr->it_status == POSIX_TIMER_REQUEUE_PENDING) {
> + /*
> + * Already queued means the timer was rearmed after
> + * the previous expiry got it on the ignore list.
> + * Nothing to do for that case.
> + */
> + if (hlist_unhashed(&tmr->ignored_list)) {
> + /*
> + * Take a signal reference and queue it on
> + * the ignored list.
> + */
> + posixtimer_sigqueue_getref(q);
> + posixtimer_sig_ignore(t, tmr);
> + }
> + } else if (!hlist_unhashed(&tmr->ignored_list)) {
> + /*
> + * Covers the case where a timer was periodic and
> + * then signal was ignored. Then it was rearmed as
> + * oneshot timer. The previous signal is invalid
> + * now, and the oneshot signal has to be dropped.
> + * Remove it from the ignored list and drop the
> + * reference count as the signal is not longer
> + * queued.
> + */
> + hlist_del_init(&tmr->ignored_list);
> + posixtimer_putref(tmr);
> + }
> goto out;
> }
>
> - ret = 0;
> + /* This should never happen and leaks a reference count */
> + if (WARN_ON_ONCE(!hlist_unhashed(&tmr->ignored_list)))
> + hlist_del_init(&tmr->ignored_list);
> +
> if (unlikely(!list_empty(&q->list))) {
> /* This holds a reference count already */
> result = TRACE_SIGNAL_ALREADY_PENDING;
> @@ -2000,7 +2045,21 @@ int posixtimer_send_sigqueue(struct k_it
> out:
> trace_signal_generate(sig, &q->info, t, tmr->it_pid_type != PIDTYPE_PID, result);
> unlock_task_sighand(t, &flags);
> - return ret;
> + return 0;
> +}
> +
> +static inline void posixtimer_sig_ignore(struct task_struct *tsk, struct sigqueue *q)
> +{
> + struct k_itimer *tmr = container_of(q, struct k_itimer, sigq);
> +
> + /*
> + * Only enqueue periodic timer signals to the ignored list. For
> + * oneshot timers, drop the reference count.
> + */
> + if (tmr->it_status == POSIX_TIMER_REQUEUE_PENDING)
This is read locklessly against timer lock. So it only makes sure that
the last write to POSIX_TIMER_REQUEUE_PENDING will be visible due to the
sighand locking. However it may or may not see the other states written after.
Which looks ok because if the timer is concurrently armed / disarmed / or even
requeue pending again, then either the signal is dropped and it's fine or the
signal is moved to the ignored list and the seq will take care of the validity
upon delivery.
Still this may need a WRITE_ONCE() / READ_ONCE().
But there is something more problematic against the delete() path:
Thread within Signal target Timer target
signal target group
-------------------- ------------- -------------
timr->it_status = POSIX_TIMER_REQUEUE_PENDING
posixtimer_send_sigqueue();
do_exit();
timer_delete()
posix_cpu_timer_del()
// return NULL
cpu_timer_task_rcu()
// timer->it_status NOT set
// to POSIX_TIMER_DISARMED
hlist_del(&timer->list);
posix_timer_cleanup_ignored()
do_sigaction(SIG_IGN...)
flush_sigqueue_mask()
sigqueue_free_ignored()
posixtimer_sig_ignore()
// Observe POSIX_TIMER_REQUEUE_PENDING
hlist_add_head(...ignored_posix_timers)
do_exit()
exit_itimers()
if (hlist_empty(&tsk->signal->posix_timers))
return;
// leaked timer queued to migrate list
> + hlist_add_head(&tmr->ignored_list, &tsk->signal->ignored_posix_timers);
> + else
> + posixtimer_putref(tmr);
> }
Thanks.
next prev parent reply other threads:[~2024-11-04 11:42 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-31 15:46 [patch v6 00/20] posix-timers: Cure the SIG_IGN mess Thomas Gleixner
2024-10-31 15:46 ` [patch v6 01/20] posix-timers: Make signal delivery consistent Thomas Gleixner
2024-11-01 12:26 ` Frederic Weisbecker
2024-10-31 15:46 ` [patch v6 02/20] posix-timers: Make signal overrun accounting sensible Thomas Gleixner
2024-11-01 12:51 ` Frederic Weisbecker
2024-11-01 20:36 ` Thomas Gleixner
2024-11-02 19:41 ` Thomas Gleixner
2024-11-02 22:57 ` Frederic Weisbecker
2024-10-31 15:46 ` [patch v6 03/20] posix-cpu-timers: Cleanup the firing logic Thomas Gleixner
2024-11-01 13:14 ` Frederic Weisbecker
2024-10-31 15:46 ` [patch v6 04/20] posix-cpu-timers: Use dedicated flag for CPU timer nanosleep Thomas Gleixner
2024-10-31 15:46 ` [patch v6 05/20] posix-timers: Add a refcount to struct k_itimer Thomas Gleixner
2024-10-31 15:46 ` [patch v6 06/20] signal: Split up __sigqueue_alloc() Thomas Gleixner
2024-10-31 15:46 ` [patch v6 07/20] signal: Provide posixtimer_sigqueue_init() Thomas Gleixner
2024-10-31 15:46 ` [patch v6 08/20] posix-timers: Store PID type in the timer Thomas Gleixner
2024-10-31 15:46 ` [patch v6 09/20] signal: Refactor send_sigqueue() Thomas Gleixner
2024-10-31 15:46 ` [patch v6 10/20] signal: Replace resched_timer logic Thomas Gleixner
2024-11-01 13:25 ` Frederic Weisbecker
2024-10-31 15:46 ` [patch v6 11/20] posix-timers: Embed sigqueue in struct k_itimer Thomas Gleixner
2024-10-31 15:46 ` [patch v6 12/20] signal: Cleanup unused posix-timer leftovers Thomas Gleixner
2024-10-31 15:46 ` [patch v6 13/20] posix-timers: Move sequence logic into struct k_itimer Thomas Gleixner
2024-10-31 15:46 ` [patch v6 14/20] signal: Provide ignored_posix_timers list Thomas Gleixner
2024-10-31 15:46 ` [patch v6 15/20] posix-timers: Handle ignored list on delete and exit Thomas Gleixner
2024-11-01 13:47 ` Frederic Weisbecker
2024-11-01 20:38 ` Thomas Gleixner
2024-10-31 15:46 ` [patch v6 16/20] signal: Handle ignored signals in do_sigaction(action != SIG_IGN) Thomas Gleixner
2024-11-01 14:04 ` Frederic Weisbecker
2024-10-31 15:46 ` [patch v6 17/20] signal: Queue ignored posixtimers on ignore list Thomas Gleixner
2024-11-01 14:21 ` Frederic Weisbecker
2024-11-01 20:47 ` Thomas Gleixner
2024-11-02 14:49 ` Thomas Gleixner
2024-11-02 20:57 ` Thomas Gleixner
2024-11-02 23:46 ` Frederic Weisbecker
2024-11-03 9:44 ` Thomas Gleixner
2024-11-03 19:55 ` Frederic Weisbecker
2024-11-02 21:05 ` [patch v6.1 " Thomas Gleixner
2024-11-04 11:42 ` Frederic Weisbecker [this message]
2024-11-04 15:21 ` Thomas Gleixner
2024-11-04 21:31 ` Thomas Gleixner
2024-11-04 23:02 ` Frederic Weisbecker
2024-10-31 15:46 ` [patch v6 18/20] posix-timers: Cleanup SIG_IGN workaround leftovers Thomas Gleixner
2024-10-31 15:46 ` [patch v6 19/20] alarmtimers: Remove the throttle mechanism from alarm_forward_now() Thomas Gleixner
2024-10-31 15:46 ` [patch v6 20/20] alarmtimers: Remove return value from alarm functions Thomas Gleixner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZyizGM4-3FmPDtGj@localhost.localdomain \
--to=frederic@kernel.org \
--cc=anna-maria@linutronix.de \
--cc=ebiederm@xmission.com \
--cc=jstultz@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=oleg@redhat.com \
--cc=peterz@infradead.org \
--cc=sboyd@kernel.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome