diff options
-rw-r--r-- | fs/exec.c | 1 | ||||
-rw-r--r-- | include/linux/sched.h | 2 | ||||
-rw-r--r-- | kernel/signal.c | 34 |
3 files changed, 37 insertions, 0 deletions
@@ -860,6 +860,7 @@ static int de_thread(struct task_struct *tsk) | |||
860 | 860 | ||
861 | no_thread_group: | 861 | no_thread_group: |
862 | exit_itimers(sig); | 862 | exit_itimers(sig); |
863 | flush_itimer_signals(); | ||
863 | if (leader) | 864 | if (leader) |
864 | release_task(leader); | 865 | release_task(leader); |
865 | 866 | ||
diff --git a/include/linux/sched.h b/include/linux/sched.h index 5395a6176f4b..3e05e5474749 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1848,7 +1848,9 @@ extern void exit_thread(void); | |||
1848 | extern void exit_files(struct task_struct *); | 1848 | extern void exit_files(struct task_struct *); |
1849 | extern void __cleanup_signal(struct signal_struct *); | 1849 | extern void __cleanup_signal(struct signal_struct *); |
1850 | extern void __cleanup_sighand(struct sighand_struct *); | 1850 | extern void __cleanup_sighand(struct sighand_struct *); |
1851 | |||
1851 | extern void exit_itimers(struct signal_struct *); | 1852 | extern void exit_itimers(struct signal_struct *); |
1853 | extern void flush_itimer_signals(void); | ||
1852 | 1854 | ||
1853 | extern NORET_TYPE void do_group_exit(int); | 1855 | extern NORET_TYPE void do_group_exit(int); |
1854 | 1856 | ||
diff --git a/kernel/signal.c b/kernel/signal.c index 2955f6c4f36e..6c0958e52ea7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -231,6 +231,40 @@ void flush_signals(struct task_struct *t) | |||
231 | spin_unlock_irqrestore(&t->sighand->siglock, flags); | 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 | void ignore_signals(struct task_struct *t) | 268 | void ignore_signals(struct task_struct *t) |
235 | { | 269 | { |
236 | int i; | 270 | int i; |