subproc: reap processes after killing

Always try to release resources if possible.

Fixes #69
This commit is contained in:
Wiktor Garbacz 2018-07-27 13:33:39 +02:00
parent ba14675185
commit bb4e77686d
3 changed files with 44 additions and 34 deletions

View File

@ -122,7 +122,7 @@ static int listenMode(nsjconf_t* nsjconf) {
} }
for (;;) { for (;;) {
if (sigFatal > 0) { if (sigFatal > 0) {
subproc::killAll(nsjconf); subproc::killAndReapAll(nsjconf);
logs::logStop(sigFatal); logs::logStop(sigFatal);
close(listenfd); close(listenfd);
return EXIT_SUCCESS; return EXIT_SUCCESS;
@ -159,7 +159,7 @@ static int standaloneMode(nsjconf_t* nsjconf) {
subproc::displayProc(nsjconf); subproc::displayProc(nsjconf);
} }
if (sigFatal > 0) { if (sigFatal > 0) {
subproc::killAll(nsjconf); subproc::killAndReapAll(nsjconf);
logs::logStop(sigFatal); logs::logStop(sigFatal);
return (128 + sigFatal); return (128 + sigFatal);
} }

View File

@ -288,8 +288,39 @@ static void seccompViolation(nsjconf_t* nsjconf, siginfo_t* si) {
} }
} }
int reapProc(nsjconf_t* nsjconf) { static int reapProc(nsjconf_t* nsjconf, pid_t pid, bool should_wait = false) {
int status; int status;
if (wait4(pid, &status, should_wait ? 0 : WNOHANG, NULL) == pid) {
cgroup::finishFromParent(nsjconf, pid);
std::string remote_txt = "[UNKNOWN]";
const pids_t* elem = getPidElem(nsjconf, pid);
if (elem) {
remote_txt = elem->remote_txt;
}
if (WIFEXITED(status)) {
LOG_I("PID: %d (%s) exited with status: %d, (PIDs left: %d)",
pid, remote_txt.c_str(), WEXITSTATUS(status),
countProc(nsjconf) - 1);
removeProc(nsjconf, pid);
return WEXITSTATUS(status);
}
if (WIFSIGNALED(status)) {
LOG_I(
"PID: %d (%s) terminated with signal: %s (%d), (PIDs left: %d)",
pid, remote_txt.c_str(),
util::sigName(WTERMSIG(status)).c_str(), WTERMSIG(status),
countProc(nsjconf) - 1);
removeProc(nsjconf, pid);
return 128 + WTERMSIG(status);
}
}
return 0;
}
int reapProc(nsjconf_t* nsjconf) {
int rv = 0; int rv = 0;
siginfo_t si; siginfo_t si;
@ -304,33 +335,7 @@ int reapProc(nsjconf_t* nsjconf) {
if (si.si_code == CLD_KILLED && si.si_status == SIGSYS) { if (si.si_code == CLD_KILLED && si.si_status == SIGSYS) {
seccompViolation(nsjconf, &si); seccompViolation(nsjconf, &si);
} }
rv = reapProc(nsjconf, si.si_pid);
if (wait4(si.si_pid, &status, WNOHANG, NULL) == si.si_pid) {
cgroup::finishFromParent(nsjconf, si.si_pid);
std::string remote_txt = "[UNKNOWN]";
const pids_t* elem = getPidElem(nsjconf, si.si_pid);
if (elem) {
remote_txt = elem->remote_txt;
}
if (WIFEXITED(status)) {
LOG_I("PID: %d (%s) exited with status: %d, (PIDs left: %d)",
si.si_pid, remote_txt.c_str(), WEXITSTATUS(status),
countProc(nsjconf) - 1);
removeProc(nsjconf, si.si_pid);
rv = WEXITSTATUS(status);
}
if (WIFSIGNALED(status)) {
LOG_I(
"PID: %d (%s) terminated with signal: %s (%d), (PIDs left: %d)",
si.si_pid, remote_txt.c_str(),
util::sigName(WTERMSIG(status)).c_str(), WTERMSIG(status),
countProc(nsjconf) - 1);
removeProc(nsjconf, si.si_pid);
rv = 128 + WTERMSIG(status);
}
}
} }
time_t now = time(NULL); time_t now = time(NULL);
@ -357,9 +362,14 @@ int reapProc(nsjconf_t* nsjconf) {
return rv; return rv;
} }
void killAll(nsjconf_t* nsjconf) { void killAndReapAll(nsjconf_t* nsjconf) {
for (const auto& p : nsjconf->pids) { while (!nsjconf->pids.empty()) {
kill(p.pid, SIGKILL); pid_t pid = nsjconf->pids.front().pid;
if (kill(pid, SIGKILL) == 0) {
reapProc(nsjconf, pid, true);
} else {
removeProc(nsjconf, pid);
}
} }
} }

View File

@ -36,7 +36,7 @@ namespace subproc {
bool runChild(nsjconf_t* nsjconf, int fd_in, int fd_out, int fd_err); bool runChild(nsjconf_t* nsjconf, int fd_in, int fd_out, int fd_err);
int countProc(nsjconf_t* nsjconf); int countProc(nsjconf_t* nsjconf);
void displayProc(nsjconf_t* nsjconf); void displayProc(nsjconf_t* nsjconf);
void killAll(nsjconf_t* nsjconf); void killAndReapAll(nsjconf_t* nsjconf);
/* Returns the exit code of the first failing subprocess, or 0 if none fail */ /* Returns the exit code of the first failing subprocess, or 0 if none fail */
int reapProc(nsjconf_t* nsjconf); int reapProc(nsjconf_t* nsjconf);
int systemExe(const std::vector<std::string>& args, char** env); int systemExe(const std::vector<std::string>& args, char** env);