mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 12:16:20 +00:00
[PATCH] ITIMER_REAL: fix possible deadlock and race
As Steven Rostedt pointed out, there are 2 problems with ITIMER_REAL timers. 1. do_setitimer() does not call del_timer_sync() in case when the timer is not pending (it_real_value() returns 0). This is wrong, the timer may still be running, and it can rearm itself. 2. It calls del_timer_sync() with tsk->sighand->siglock held. This is deadlockable, because timer's handler needs this lock too. Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru> Acked-by: Steven Rostedt <rostedt@goodmis.org> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
b36bbb6c3d
commit
f01b1b0baa
1 changed files with 6 additions and 2 deletions
|
@ -153,11 +153,15 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
|
||||||
|
|
||||||
switch (which) {
|
switch (which) {
|
||||||
case ITIMER_REAL:
|
case ITIMER_REAL:
|
||||||
|
again:
|
||||||
spin_lock_irq(&tsk->sighand->siglock);
|
spin_lock_irq(&tsk->sighand->siglock);
|
||||||
interval = tsk->signal->it_real_incr;
|
interval = tsk->signal->it_real_incr;
|
||||||
val = it_real_value(tsk->signal);
|
val = it_real_value(tsk->signal);
|
||||||
if (val)
|
/* We are sharing ->siglock with it_real_fn() */
|
||||||
del_timer_sync(&tsk->signal->real_timer);
|
if (try_to_del_timer_sync(&tsk->signal->real_timer) < 0) {
|
||||||
|
spin_unlock_irq(&tsk->sighand->siglock);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
tsk->signal->it_real_incr =
|
tsk->signal->it_real_incr =
|
||||||
timeval_to_jiffies(&value->it_interval);
|
timeval_to_jiffies(&value->it_interval);
|
||||||
it_real_arm(tsk, timeval_to_jiffies(&value->it_value));
|
it_real_arm(tsk, timeval_to_jiffies(&value->it_value));
|
||||||
|
|
Loading…
Reference in a new issue