Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

signal: Refactor send_sigqueue()

To handle posix timers which have their signal ignored via SIG_IGN properly
it is required to requeue a ignored signal for delivery when SIG_IGN is
lifted so the timer gets rearmed.

Split the required code out of send_sigqueue() so it can be reused in
context of sigaction().

While at it rename send_sigqueue() to posixtimer_send_sigqueue() so its
clear what this is about.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/all/20241105064213.586453412@linutronix.de

+47 -39
+1
include/linux/posix-timers.h
··· 109 109 110 110 void posixtimer_rearm_itimer(struct task_struct *p); 111 111 bool posixtimer_init_sigqueue(struct sigqueue *q); 112 + int posixtimer_send_sigqueue(struct k_itimer *tmr); 112 113 bool posixtimer_deliver_signal(struct kernel_siginfo *info); 113 114 void posixtimer_free_timer(struct k_itimer *timer); 114 115
-1
include/linux/sched/signal.h
··· 340 340 extern int zap_other_threads(struct task_struct *p); 341 341 extern struct sigqueue *sigqueue_alloc(void); 342 342 extern void sigqueue_free(struct sigqueue *); 343 - extern int send_sigqueue(struct sigqueue *, struct pid *, enum pid_type, int si_private); 344 343 extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *); 345 344 346 345 static inline void clear_notify_signal(void)
+45 -37
kernel/signal.c
··· 1947 1947 __sigqueue_free(q); 1948 1948 } 1949 1949 1950 - int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type, int si_private) 1950 + static void posixtimer_queue_sigqueue(struct sigqueue *q, struct task_struct *t, enum pid_type type) 1951 1951 { 1952 - int sig = q->info.si_signo; 1953 1952 struct sigpending *pending; 1953 + int sig = q->info.si_signo; 1954 + 1955 + signalfd_notify(t, sig); 1956 + pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending; 1957 + list_add_tail(&q->list, &pending->list); 1958 + sigaddset(&pending->signal, sig); 1959 + complete_signal(sig, t, type); 1960 + } 1961 + 1962 + /* 1963 + * This function is used by POSIX timers to deliver a timer signal. 1964 + * Where type is PIDTYPE_PID (such as for timers with SIGEV_THREAD_ID 1965 + * set), the signal must be delivered to the specific thread (queues 1966 + * into t->pending). 1967 + * 1968 + * Where type is not PIDTYPE_PID, signals must be delivered to the 1969 + * process. In this case, prefer to deliver to current if it is in 1970 + * the same thread group as the target process, which avoids 1971 + * unnecessarily waking up a potentially idle task. 1972 + */ 1973 + static inline struct task_struct *posixtimer_get_target(struct k_itimer *tmr) 1974 + { 1975 + struct task_struct *t = pid_task(tmr->it_pid, tmr->it_pid_type); 1976 + 1977 + if (t && tmr->it_pid_type != PIDTYPE_PID && same_thread_group(t, current)) 1978 + t = current; 1979 + return t; 1980 + } 1981 + 1982 + int posixtimer_send_sigqueue(struct k_itimer *tmr) 1983 + { 1984 + struct sigqueue *q = tmr->sigq; 1985 + int sig = q->info.si_signo; 1954 1986 struct task_struct *t; 1955 1987 unsigned long flags; 1956 1988 int ret, result; 1957 1989 1958 - if (WARN_ON_ONCE(!(q->flags & SIGQUEUE_PREALLOC))) 1959 - return 0; 1960 - if (WARN_ON_ONCE(q->info.si_code != SI_TIMER)) 1961 - return 0; 1990 + guard(rcu)(); 1962 1991 1963 - ret = -1; 1964 - rcu_read_lock(); 1965 - 1966 - /* 1967 - * This function is used by POSIX timers to deliver a timer signal. 1968 - * Where type is PIDTYPE_PID (such as for timers with SIGEV_THREAD_ID 1969 - * set), the signal must be delivered to the specific thread (queues 1970 - * into t->pending). 1971 - * 1972 - * Where type is not PIDTYPE_PID, signals must be delivered to the 1973 - * process. In this case, prefer to deliver to current if it is in 1974 - * the same thread group as the target process, which avoids 1975 - * unnecessarily waking up a potentially idle task. 1976 - */ 1977 - t = pid_task(pid, type); 1992 + t = posixtimer_get_target(tmr); 1978 1993 if (!t) 1979 - goto ret; 1980 - if (type != PIDTYPE_PID && same_thread_group(t, current)) 1981 - t = current; 1994 + return -1; 1995 + 1982 1996 if (!likely(lock_task_sighand(t, &flags))) 1983 - goto ret; 1997 + return -1; 1984 1998 1985 1999 /* 1986 2000 * Update @q::info::si_sys_private for posix timer signals with ··· 2002 1988 * decides based on si_sys_private whether to invoke 2003 1989 * posixtimer_rearm() or not. 2004 1990 */ 2005 - q->info.si_sys_private = si_private; 1991 + q->info.si_sys_private = tmr->it_signal_seq; 2006 1992 2007 1993 ret = 1; /* the signal is ignored */ 2008 - result = TRACE_SIGNAL_IGNORED; 2009 - if (!prepare_signal(sig, t, false)) 1994 + if (!prepare_signal(sig, t, false)) { 1995 + result = TRACE_SIGNAL_IGNORED; 2010 1996 goto out; 1997 + } 2011 1998 2012 1999 ret = 0; 2013 2000 if (unlikely(!list_empty(&q->list))) { 2014 2001 result = TRACE_SIGNAL_ALREADY_PENDING; 2015 2002 goto out; 2016 2003 } 2017 - 2018 - signalfd_notify(t, sig); 2019 - pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending; 2020 - list_add_tail(&q->list, &pending->list); 2021 - sigaddset(&pending->signal, sig); 2022 - complete_signal(sig, t, type); 2004 + posixtimer_queue_sigqueue(q, t, tmr->it_pid_type); 2023 2005 result = TRACE_SIGNAL_DELIVERED; 2024 2006 out: 2025 - trace_signal_generate(sig, &q->info, t, type != PIDTYPE_PID, result); 2007 + trace_signal_generate(sig, &q->info, t, tmr->it_pid_type != PIDTYPE_PID, result); 2026 2008 unlock_task_sighand(t, &flags); 2027 - ret: 2028 - rcu_read_unlock(); 2029 2009 return ret; 2030 2010 } 2031 2011 #endif /* CONFIG_POSIX_TIMERS */
+1 -1
kernel/time/posix-timers.c
··· 307 307 308 308 timr->it_status = state; 309 309 310 - ret = send_sigqueue(timr->sigq, timr->it_pid, timr->it_pid_type, timr->it_signal_seq); 310 + ret = posixtimer_send_sigqueue(timr); 311 311 /* If we failed to send the signal the timer stops. */ 312 312 return ret > 0; 313 313 }