mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-19 16:14:13 +08:00
[PATCH] do_coredump() should reset group_stop_count earlier
__group_complete_signal() sets ->group_stop_count in sig_kernel_coredump() path and marks the target thread as ->group_exit_task. So any thread except group_exit_task will go to handle_group_stop()->finish_stop(). However, when group_exit_task actually starts do_coredump(), it sets SIGNAL_GROUP_EXIT, but does not reset ->group_stop_count while killing other threads. If we have not yet stopped threads in the same thread group, they all will spin in kernel mode until group_exit_task sends them SIGKILL, because ->group_stop_count > 0 means: recalc_sigpending_tsk() never clears TIF_SIGPENDING get_signal_to_deliver() goes to handle_group_stop() handle_group_stop() returns when SIGNAL_GROUP_EXIT set syscall_exit/resume_userspace notice TIF_SIGPENDING, call get_signal_to_deliver() again. So we are wasting cpu cycles, and if one of these threads is rt_task() this may be a serious problem. NOTE: do_coredump() holds ->mmap_sem, so not stopped threads can't escape coredumping after clearing ->group_stop_count. See also this thread: http://marc.theaimsgroup.com/?t=112739139900002 Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
0811af28ce
commit
bb6f6dbaa4
@ -1462,6 +1462,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
|
||||
if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
|
||||
current->signal->flags = SIGNAL_GROUP_EXIT;
|
||||
current->signal->group_exit_code = exit_code;
|
||||
current->signal->group_stop_count = 0;
|
||||
retval = 0;
|
||||
}
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
@ -1477,7 +1478,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
|
||||
* Clear any false indication of pending signals that might
|
||||
* be seen by the filesystem code called to write the core file.
|
||||
*/
|
||||
current->signal->group_stop_count = 0;
|
||||
clear_thread_flag(TIF_SIGPENDING);
|
||||
|
||||
if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
|
||||
|
Loading…
Reference in New Issue
Block a user