61 lines
2.2 KiB
Diff
61 lines
2.2 KiB
Diff
From 78dfb59b62d1a7735cd28fc2783e58c122954fae Mon Sep 17 00:00:00 2001
|
|
From: Oleg Nesterov <oleg@redhat.com>
|
|
Date: Fri, 5 Nov 2010 16:53:42 +0100
|
|
Subject: posix-cpu-timers: workaround to suppress the problems with mt exec
|
|
|
|
posix-cpu-timers.c correctly assumes that the dying process does
|
|
posix_cpu_timers_exit_group() and removes all !CPUCLOCK_PERTHREAD
|
|
timers from signal->cpu_timers list.
|
|
|
|
But, it also assumes that timer->it.cpu.task is always the group
|
|
leader, and thus the dead ->task means the dead thread group.
|
|
|
|
This is obviously not true after de_thread() changes the leader.
|
|
After that almost every posix_cpu_timer_ method has problems.
|
|
|
|
It is not simple to fix this bug correctly. First of all, I think
|
|
that timer->it.cpu should use struct pid instead of task_struct.
|
|
Also, the locking should be reworked completely. In particular,
|
|
tasklist_lock should not be used at all. This all needs a lot of
|
|
nontrivial and hard-to-test changes.
|
|
|
|
Change __exit_signal() to do posix_cpu_timers_exit_group() when
|
|
the old leader dies during exec. This is not the fix, just the
|
|
temporary hack to hide the problem for 2.6.37 and stable. IOW,
|
|
this is obviously wrong but this is what we currently have anyway:
|
|
cpu timers do not work after mt exec.
|
|
|
|
In theory this change adds another race. The exiting leader can
|
|
detach the timers which were attached to the new leader. However,
|
|
the window between de_thread() and release_task() is small, we
|
|
can pretend that sys_timer_create() was called before de_thread().
|
|
|
|
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
|
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
|
---
|
|
kernel/exit.c | 8 ++++++++
|
|
1 files changed, 8 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/kernel/exit.c b/kernel/exit.c
|
|
index 0312022..1eff9e4 100644
|
|
--- a/kernel/exit.c
|
|
+++ b/kernel/exit.c
|
|
@@ -95,6 +95,14 @@ static void __exit_signal(struct task_struct *tsk)
|
|
sig->tty = NULL;
|
|
} else {
|
|
/*
|
|
+ * This can only happen if the caller is de_thread().
|
|
+ * FIXME: this is the temporary hack, we should teach
|
|
+ * posix-cpu-timers to handle this case correctly.
|
|
+ */
|
|
+ if (unlikely(has_group_leader_pid(tsk)))
|
|
+ posix_cpu_timers_exit_group(tsk);
|
|
+
|
|
+ /*
|
|
* If there is any task waiting for the group exit
|
|
* then notify it:
|
|
*/
|
|
--
|
|
1.7.3.2
|
|
|