diff options
Diffstat (limited to 'kernel/exit.c')
| -rw-r--r-- | kernel/exit.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 1ea4369890a3..feff10bbb307 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -435,7 +435,8 @@ static void exit_mm(struct task_struct *tsk) | |||
| 435 | task_unlock(tsk); | 435 | task_unlock(tsk); |
| 436 | mm_update_next_owner(mm); | 436 | mm_update_next_owner(mm); |
| 437 | mmput(mm); | 437 | mmput(mm); |
| 438 | clear_thread_flag(TIF_MEMDIE); | 438 | if (test_thread_flag(TIF_MEMDIE)) |
| 439 | unmark_oom_victim(); | ||
| 439 | } | 440 | } |
| 440 | 441 | ||
| 441 | static struct task_struct *find_alive_thread(struct task_struct *p) | 442 | static struct task_struct *find_alive_thread(struct task_struct *p) |
| @@ -1287,9 +1288,15 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p) | |||
| 1287 | static int wait_consider_task(struct wait_opts *wo, int ptrace, | 1288 | static int wait_consider_task(struct wait_opts *wo, int ptrace, |
| 1288 | struct task_struct *p) | 1289 | struct task_struct *p) |
| 1289 | { | 1290 | { |
| 1291 | /* | ||
| 1292 | * We can race with wait_task_zombie() from another thread. | ||
| 1293 | * Ensure that EXIT_ZOMBIE -> EXIT_DEAD/EXIT_TRACE transition | ||
| 1294 | * can't confuse the checks below. | ||
| 1295 | */ | ||
| 1296 | int exit_state = ACCESS_ONCE(p->exit_state); | ||
| 1290 | int ret; | 1297 | int ret; |
| 1291 | 1298 | ||
| 1292 | if (unlikely(p->exit_state == EXIT_DEAD)) | 1299 | if (unlikely(exit_state == EXIT_DEAD)) |
| 1293 | return 0; | 1300 | return 0; |
| 1294 | 1301 | ||
| 1295 | ret = eligible_child(wo, p); | 1302 | ret = eligible_child(wo, p); |
| @@ -1310,7 +1317,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace, | |||
| 1310 | return 0; | 1317 | return 0; |
| 1311 | } | 1318 | } |
| 1312 | 1319 | ||
| 1313 | if (unlikely(p->exit_state == EXIT_TRACE)) { | 1320 | if (unlikely(exit_state == EXIT_TRACE)) { |
| 1314 | /* | 1321 | /* |
| 1315 | * ptrace == 0 means we are the natural parent. In this case | 1322 | * ptrace == 0 means we are the natural parent. In this case |
| 1316 | * we should clear notask_error, debugger will notify us. | 1323 | * we should clear notask_error, debugger will notify us. |
| @@ -1337,7 +1344,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace, | |||
| 1337 | } | 1344 | } |
| 1338 | 1345 | ||
| 1339 | /* slay zombie? */ | 1346 | /* slay zombie? */ |
| 1340 | if (p->exit_state == EXIT_ZOMBIE) { | 1347 | if (exit_state == EXIT_ZOMBIE) { |
| 1341 | /* we don't reap group leaders with subthreads */ | 1348 | /* we don't reap group leaders with subthreads */ |
| 1342 | if (!delay_group_leader(p)) { | 1349 | if (!delay_group_leader(p)) { |
| 1343 | /* | 1350 | /* |
