aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/exec.c1
-rw-r--r--include/linux/sched.h2
-rw-r--r--kernel/signal.c34
3 files changed, 37 insertions, 0 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 3c2ba7ce11d4..9448f1b50b4a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -860,6 +860,7 @@ static int de_thread(struct task_struct *tsk)
860 860
861no_thread_group: 861no_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);
1848extern void exit_files(struct task_struct *); 1848extern void exit_files(struct task_struct *);
1849extern void __cleanup_signal(struct signal_struct *); 1849extern void __cleanup_signal(struct signal_struct *);
1850extern void __cleanup_sighand(struct sighand_struct *); 1850extern void __cleanup_sighand(struct sighand_struct *);
1851
1851extern void exit_itimers(struct signal_struct *); 1852extern void exit_itimers(struct signal_struct *);
1853extern void flush_itimer_signals(void);
1852 1854
1853extern NORET_TYPE void do_group_exit(int); 1855extern 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
234static 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
257void 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
234void ignore_signals(struct task_struct *t) 268void ignore_signals(struct task_struct *t)
235{ 269{
236 int i; 270 int i;