|
@@ -81,13 +81,33 @@ int freeze_processes(void)
|
|
|
} while_each_thread(g, p);
|
|
|
read_unlock(&tasklist_lock);
|
|
|
yield(); /* Yield is okay here */
|
|
|
- if (time_after(jiffies, start_time + TIMEOUT)) {
|
|
|
+ if (todo && time_after(jiffies, start_time + TIMEOUT)) {
|
|
|
printk( "\n" );
|
|
|
printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo );
|
|
|
- return todo;
|
|
|
+ break;
|
|
|
}
|
|
|
} while(todo);
|
|
|
|
|
|
+ /* This does not unfreeze processes that are already frozen
|
|
|
+ * (we have slightly ugly calling convention in that respect,
|
|
|
+ * and caller must call thaw_processes() if something fails),
|
|
|
+ * but it cleans up leftover PF_FREEZE requests.
|
|
|
+ */
|
|
|
+ if (todo) {
|
|
|
+ read_lock(&tasklist_lock);
|
|
|
+ do_each_thread(g, p)
|
|
|
+ if (freezing(p)) {
|
|
|
+ pr_debug(" clean up: %s\n", p->comm);
|
|
|
+ p->flags &= ~PF_FREEZE;
|
|
|
+ spin_lock_irqsave(&p->sighand->siglock, flags);
|
|
|
+ recalc_sigpending_tsk(p);
|
|
|
+ spin_unlock_irqrestore(&p->sighand->siglock, flags);
|
|
|
+ }
|
|
|
+ while_each_thread(g, p);
|
|
|
+ read_unlock(&tasklist_lock);
|
|
|
+ return todo;
|
|
|
+ }
|
|
|
+
|
|
|
printk( "|\n" );
|
|
|
BUG_ON(in_atomic());
|
|
|
return 0;
|