summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMandeep Singh Baines <msb@chromium.org>2012-01-03 14:41:13 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-03 16:14:32 -0800
commitf9fab10bbd768b0e5254e53a4a8477a94bfc4b96 (patch)
tree7f4efb5c46582765c12249f652a8975a1956f781
parent30e053248da178cf6154bb7e950dc8713567e3fa (diff)
downloadlinux-f9fab10bbd768b0e5254e53a4a8477a94bfc4b96.tar.gz
linux-f9fab10bbd768b0e5254e53a4a8477a94bfc4b96.tar.bz2
linux-f9fab10bbd768b0e5254e53a4a8477a94bfc4b96.zip
hung_task: fix false positive during vfork
vfork parent uninterruptibly and unkillably waits for its child to exec/exit. This wait is of unbounded length. Ignore such waits in the hung_task detector. Signed-off-by: Mandeep Singh Baines <msb@chromium.org> Reported-by: Sasha Levin <levinsasha928@gmail.com> LKML-Reference: <1325344394.28904.43.camel@lappy> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: John Kacur <jkacur@redhat.com> Cc: stable@kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/hung_task.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 8b1748d0172c..2e48ec0c2e91 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -74,11 +74,17 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
/*
* Ensure the task is not frozen.
- * Also, when a freshly created task is scheduled once, changes
- * its state to TASK_UNINTERRUPTIBLE without having ever been
- * switched out once, it musn't be checked.
+ * Also, skip vfork and any other user process that freezer should skip.
*/
- if (unlikely(t->flags & PF_FROZEN || !switch_count))
+ if (unlikely(t->flags & (PF_FROZEN | PF_FREEZER_SKIP)))
+ return;
+
+ /*
+ * When a freshly created task is scheduled once, changes its state to
+ * TASK_UNINTERRUPTIBLE without having ever been switched out once, it
+ * musn't be checked.
+ */
+ if (unlikely(!switch_count))
return;
if (switch_count != t->last_switch_count) {