libutil: kill process groups properly
we can have a ProcessGroup for a pid that *should* be a process group but hasn't gotten around to setting its pgid yet. in such cases we do want to be killing the thing anyway, not shoot into the void and hope the right thing falls over. so far this has not been a problem due to a mixture of just not having done this and being slow enough to work. Change-Id: I4e0e54513252d8e18256b9286b819bfa957d70dc
This commit is contained in:
@@ -106,14 +106,23 @@ int ProcessGroup::kill()
|
||||
|
||||
debug("killing process group %1%", leader.get());
|
||||
|
||||
// send a kill signal to the leader *only* first. the leader we know may not have
|
||||
// actually set its pgid yet, in which case the following kill for the group will
|
||||
// fail. if this happens we still want to clean up the whole (hopefully singular)
|
||||
// group, thus we start small. we will always attempt to kill the group too; only
|
||||
// when we've waited on the pid we know can it be reused as a pgid. we are not in
|
||||
// danger of killing any other processes we don't want to be killing as a result.
|
||||
const auto leaderKillResult = ::kill(leader.get(), SIGKILL);
|
||||
(void) leaderKillResult;
|
||||
|
||||
/* Send the requested signal to every process in the child
|
||||
process group (which hopefully includes *all* its children). */
|
||||
if (::kill(-leader.get(), SIGKILL) != 0) {
|
||||
if (::kill(-leader.get(), SIGKILL) != 0 && errno != ESRCH) {
|
||||
/* On BSDs, killing a process group will return EPERM if all
|
||||
processes in the group are zombies (or something like
|
||||
that). So try to detect and ignore that situation. */
|
||||
#if __FreeBSD__ || __APPLE__
|
||||
if (errno != EPERM || ::kill(leader.get(), 0) != 0)
|
||||
if (errno != EPERM || leaderKillResult != 0)
|
||||
#endif
|
||||
logError(SysError("killing process group %d", leader.get()).info());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user