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.

posix timers: discard SI_TIMER signals on exec

Based on Roland's patch. This approach was suggested by Austin Clements
from the very beginning, and then by Linus.

As Austin pointed out, the execing task can be killed by SI_TIMER signal
because exec flushes the signal handlers, but doesn't discard the pending
signals generated by posix timers. Perhaps not a bug, but people find this
surprising. See http://bugzilla.kernel.org/show_bug.cgi?id=10460

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Austin Clements <amdragon+kernelbugzilla@mit.edu>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Oleg Nesterov and committed by
Linus Torvalds
cbaffba1 c8e85b4f

+37
+1
fs/exec.c
··· 860 860 861 861 no_thread_group: 862 862 exit_itimers(sig); 863 + flush_itimer_signals(); 863 864 if (leader) 864 865 release_task(leader); 865 866
+2
include/linux/sched.h
··· 1848 1848 extern void exit_files(struct task_struct *); 1849 1849 extern void __cleanup_signal(struct signal_struct *); 1850 1850 extern void __cleanup_sighand(struct sighand_struct *); 1851 + 1851 1852 extern void exit_itimers(struct signal_struct *); 1853 + extern void flush_itimer_signals(void); 1852 1854 1853 1855 extern NORET_TYPE void do_group_exit(int); 1854 1856
+34
kernel/signal.c
··· 231 231 spin_unlock_irqrestore(&t->sighand->siglock, flags); 232 232 } 233 233 234 + static void __flush_itimer_signals(struct sigpending *pending) 235 + { 236 + sigset_t signal, retain; 237 + struct sigqueue *q, *n; 238 + 239 + signal = pending->signal; 240 + sigemptyset(&retain); 241 + 242 + list_for_each_entry_safe(q, n, &pending->list, list) { 243 + int sig = q->info.si_signo; 244 + 245 + if (likely(q->info.si_code != SI_TIMER)) { 246 + sigaddset(&retain, sig); 247 + } else { 248 + sigdelset(&signal, sig); 249 + list_del_init(&q->list); 250 + __sigqueue_free(q); 251 + } 252 + } 253 + 254 + sigorsets(&pending->signal, &signal, &retain); 255 + } 256 + 257 + void flush_itimer_signals(void) 258 + { 259 + struct task_struct *tsk = current; 260 + unsigned long flags; 261 + 262 + spin_lock_irqsave(&tsk->sighand->siglock, flags); 263 + __flush_itimer_signals(&tsk->pending); 264 + __flush_itimer_signals(&tsk->signal->shared_pending); 265 + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 266 + } 267 + 234 268 void ignore_signals(struct task_struct *t) 235 269 { 236 270 int i;