Re: [PATCH 02/14] freezer: fix a race during freezing of TASK_STOPPED tasks

From: Rafael J. Wysocki
Date: Fri Nov 26 2010 - 14:41:48 EST


On Friday, November 26, 2010, Tejun Heo wrote:
> After calling freeze_task(), try_to_freeze_tasks() see whether the
> task is stopped or traced and if so, considers it to be frozen;
> however, nothing guarantees that either the task being frozen sees
> TIF_FREEZE or the freezer sees TASK_STOPPED -> TASK_RUNNING
> transition. The task being frozen may wake up and not see TIF_FREEZE
> while the freezer fails to notice the transition and believes the task
> is still stopped.
>
> This patch fixes the race by making freeze_task() always go through
> fake_signal_wake_up() for applicable tasks. The function goes through
> the target task's scheduler lock and thus guarantees that either the
> target sees TIF_FREEZE or try_to_freeze_task() sees TASK_RUNNING.

Looks good. I'll take this one to my tree, if you don't mind.

Thanks,
Rafael


> Signed-off-by: Tejun Heo <tj@xxxxxxxxxx>
> Cc: Oleg Nesterov <oleg@xxxxxxxxxx>
> Cc: Rafael J. Wysocki <rjw@xxxxxxx>
> ---
> kernel/freezer.c | 9 +++++++--
> kernel/power/process.c | 6 ++++++
> 2 files changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/freezer.c b/kernel/freezer.c
> index bd1d42b..66ecd2e 100644
> --- a/kernel/freezer.c
> +++ b/kernel/freezer.c
> @@ -104,8 +104,13 @@ bool freeze_task(struct task_struct *p, bool sig_only)
> }
>
> if (should_send_signal(p)) {
> - if (!signal_pending(p))
> - fake_signal_wake_up(p);
> + fake_signal_wake_up(p);
> + /*
> + * fake_signal_wake_up() goes through p's scheduler
> + * lock and guarantees that TASK_STOPPED/TRACED ->
> + * TASK_RUNNING transition can't race with task state
> + * testing in try_to_freeze_tasks().
> + */
> } else if (sig_only) {
> return false;
> } else {
> diff --git a/kernel/power/process.c b/kernel/power/process.c
> index e50b4c1..eb2c88a 100644
> --- a/kernel/power/process.c
> +++ b/kernel/power/process.c
> @@ -64,6 +64,12 @@ static int try_to_freeze_tasks(bool sig_only)
> * perturb a task in TASK_STOPPED or TASK_TRACED.
> * It is "frozen enough". If the task does wake
> * up, it will immediately call try_to_freeze.
> + *
> + * Because freeze_task() goes through p's
> + * scheduler lock after setting TIF_FREEZE, it's
> + * guaranteed that either we see TASK_RUNNING or
> + * try_to_stop() after schedule() in ptrace/signal
> + * stop sees TIF_FREEZE.
> */
> if (!task_is_stopped_or_traced(p) &&
> !freezer_should_skip(p))
>

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/