diff options
Diffstat (limited to 'kernel/time/posix-timers.c')
| -rw-r--r-- | kernel/time/posix-timers.c | 19 | 
1 files changed, 14 insertions, 5 deletions
| diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 1cd10b102c51..5dead89308b7 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -1051,15 +1051,24 @@ retry_delete:  }  /* - * This is called by do_exit or de_thread, only when there are no more - * references to the shared signal_struct. + * This is called by do_exit or de_thread, only when nobody else can + * modify the signal->posix_timers list. Yet we need sighand->siglock + * to prevent the race with /proc/pid/timers.   */ -void exit_itimers(struct signal_struct *sig) +void exit_itimers(struct task_struct *tsk)  { +	struct list_head timers;  	struct k_itimer *tmr; -	while (!list_empty(&sig->posix_timers)) { -		tmr = list_entry(sig->posix_timers.next, struct k_itimer, list); +	if (list_empty(&tsk->signal->posix_timers)) +		return; + +	spin_lock_irq(&tsk->sighand->siglock); +	list_replace_init(&tsk->signal->posix_timers, &timers); +	spin_unlock_irq(&tsk->sighand->siglock); + +	while (!list_empty(&timers)) { +		tmr = list_first_entry(&timers, struct k_itimer, list);  		itimer_delete(tmr);  	}  } | 
