Skip to content

Commit c257a34

Browse files
rientjestorvalds
authored andcommitted
fs, epoll: short circuit fetching events if thread has been killed
We've encountered zombies that are waiting for a thread to exit that are looping in ep_poll() almost endlessly although there is a pending SIGKILL as a result of a group exit. This happens because we always find ep_events_available() and fetch more events and never are able to check for signal_pending() that would break from the loop and return -EINTR. Special case fatal signals and break immediately to guarantee that we loop to fetch more events and delay making a timely exit. It would also be possible to simply move the check for signal_pending() higher than checking for ep_events_available(), but there have been no reports of delayed signal handling other than SIGKILL preventing zombies from exiting that would be fixed by this. It fixes an issue for us where we have witnessed zombies sticking around for at least O(minutes), but considering the code has been like this forever and nobody else has complained that I have found, I would simply queue it up for 4.12. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: David Rientjes <[email protected]> Cc: Alexander Viro <[email protected]> Cc: Jan Kara <[email protected]> Cc: Davide Libenzi <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent fd71f63 commit c257a34

File tree

1 file changed

+10
-0
lines changed

1 file changed

+10
-0
lines changed

fs/eventpoll.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,6 +1748,16 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
17481748
* to TASK_INTERRUPTIBLE before doing the checks.
17491749
*/
17501750
set_current_state(TASK_INTERRUPTIBLE);
1751+
/*
1752+
* Always short-circuit for fatal signals to allow
1753+
* threads to make a timely exit without the chance of
1754+
* finding more events available and fetching
1755+
* repeatedly.
1756+
*/
1757+
if (fatal_signal_pending(current)) {
1758+
res = -EINTR;
1759+
break;
1760+
}
17511761
if (ep_events_available(ep) || timed_out)
17521762
break;
17531763
if (signal_pending(current)) {

0 commit comments

Comments
 (0)