On Fri, Apr 20, 2007 at 10:02:08PM +0400, Oleg Nesterov wrote:
Actually yes. The idea anyway was to check one last time before declaring
ourselves as frozen. So I thought the best place was inside refrigerator since
we are already holding the task_lock there.
I wasn't too sure about calling recalc_sigpending(), but now that you
mention it, I agree, this would be a nicer way to do it.
Btw, since frozen_process is currently being called only from
refrigerator, I am wondering if we still need the struct task_struct *p
parameter there. It's very unlikely that some other task would mark a
particular task as frozen. No?
Anyways, Andrew, Could you please replace the earlier sent patch titled
"fix_pf_nofreeze_and_freezeable_race.patch" with the following one?
Thanks and Regards
gautham.
-->
This patch fixes the race pointed out by Oleg Nesterov.
* Freezer marks a thread as freezeable.
* The thread now marks itself PF_NOFREEZE causing it to
freeze on calling try_to_freeze(). Thus the task is frozen, even though
it doesn't want to.
* Subsequent thaw_processes() will also fail to thaw the task since it is
marked PF_NOFREEZE.
Avoid this problem by checking the task's PF_NOFREEZE status in
frozen_processes() before marking the task as frozen.
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
---
include/linux/freezer.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
Index: linux-2.6.21-rc6/include/linux/freezer.h
===================================================================
--- linux-2.6.21-rc6.orig/include/linux/freezer.h
+++ linux-2.6.21-rc6/include/linux/freezer.h
@@ -57,8 +57,10 @@ static inline int thaw_process(struct ta
*/
static inline void frozen_process(struct task_struct *p)
{
- p->flags |= PF_FROZEN;
- wmb();
+ if (!unlikely(p->flags & PF_NOFREEZE)) {
+ p->flags |= PF_FROZEN;
+ wmb();
+ }
clear_tsk_thread_flag(p, TIF_FREEZE);
}
--
Gautham R Shenoy
Linux Technology Center
IBM India.
"Freedom comes with a price tag of responsibility, which is still a bargain,
because Freedom is priceless!"
-