diff options
Diffstat (limited to 'mm/oom_kill.c')
| -rw-r--r-- | mm/oom_kill.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index f0e8cd9edb1a..26ea8636758f 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
| @@ -647,8 +647,8 @@ static int oom_reaper(void *unused) | |||
| 647 | 647 | ||
| 648 | static void wake_oom_reaper(struct task_struct *tsk) | 648 | static void wake_oom_reaper(struct task_struct *tsk) |
| 649 | { | 649 | { |
| 650 | /* tsk is already queued? */ | 650 | /* mm is already queued? */ |
| 651 | if (tsk == oom_reaper_list || tsk->oom_reaper_list) | 651 | if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags)) |
| 652 | return; | 652 | return; |
| 653 | 653 | ||
| 654 | get_task_struct(tsk); | 654 | get_task_struct(tsk); |
| @@ -975,6 +975,13 @@ static void oom_kill_process(struct oom_control *oc, const char *message) | |||
| 975 | * still freeing memory. | 975 | * still freeing memory. |
| 976 | */ | 976 | */ |
| 977 | read_lock(&tasklist_lock); | 977 | read_lock(&tasklist_lock); |
| 978 | |||
| 979 | /* | ||
| 980 | * The task 'p' might have already exited before reaching here. The | ||
| 981 | * put_task_struct() will free task_struct 'p' while the loop still try | ||
| 982 | * to access the field of 'p', so, get an extra reference. | ||
| 983 | */ | ||
| 984 | get_task_struct(p); | ||
| 978 | for_each_thread(p, t) { | 985 | for_each_thread(p, t) { |
| 979 | list_for_each_entry(child, &t->children, sibling) { | 986 | list_for_each_entry(child, &t->children, sibling) { |
| 980 | unsigned int child_points; | 987 | unsigned int child_points; |
| @@ -994,6 +1001,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message) | |||
| 994 | } | 1001 | } |
| 995 | } | 1002 | } |
| 996 | } | 1003 | } |
| 1004 | put_task_struct(p); | ||
| 997 | read_unlock(&tasklist_lock); | 1005 | read_unlock(&tasklist_lock); |
| 998 | 1006 | ||
| 999 | /* | 1007 | /* |
