| From 4bffa244222d6b3400658fbb7f647cc797f1b1f7 Mon Sep 17 00:00:00 2001 |
| From: Oleg Nesterov <oleg@redhat.com> |
| Date: Fri, 5 Nov 2010 16:53:42 +0100 |
| Subject: [PATCH] posix-cpu-timers: workaround to suppress the problems with |
| mt exec |
| |
| commit e0a70217107e6f9844628120412cb27bb4cea194 upstream. |
| |
| 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> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/kernel/exit.c b/kernel/exit.c |
| index 8eb207f..a652c26 100644 |
| --- a/kernel/exit.c |
| +++ b/kernel/exit.c |
| @@ -95,6 +95,14 @@ static void __exit_signal(struct task_struct *tsk) |
| posix_cpu_timers_exit_group(tsk); |
| 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.4.4 |
| |