summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mm/oom_kill.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 5340f6b91312d..dc8487de9edf2 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -464,6 +464,13 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
* still freeing memory.
*/
read_lock(&tasklist_lock);
+
+ /*
+ * The task 'p' might have already exited before reaching here. The
+ * put_task_struct() will free task_struct 'p' while the loop still try
+ * to access the field of 'p', so, get an extra reference.
+ */
+ get_task_struct(p);
for_each_thread(p, t) {
list_for_each_entry(child, &t->children, sibling) {
unsigned int child_points;
@@ -483,6 +490,7 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
}
}
}
+ put_task_struct(p);
read_unlock(&tasklist_lock);
p = find_lock_task_mm(victim);