* Terminate build hooks and substitutes with a TERM signal, not a KILL
signal. This is necessary because those processes may have joined the BDB environment, so they have to be given a chance to clean up. (NIX-85)
This commit is contained in:
parent
b2b6cf3fc8
commit
8ab229ddf2
3 changed files with 27 additions and 10 deletions
|
@ -628,7 +628,7 @@ private:
|
||||||
HookReply tryBuildHook();
|
HookReply tryBuildHook();
|
||||||
|
|
||||||
/* Synchronously wait for a build hook to finish. */
|
/* Synchronously wait for a build hook to finish. */
|
||||||
void terminateBuildHook();
|
void terminateBuildHook(bool kill = false);
|
||||||
|
|
||||||
/* Acquires locks on the output paths and gathers information
|
/* Acquires locks on the output paths and gathers information
|
||||||
about the build (e.g., the input closures). During this
|
about the build (e.g., the input closures). During this
|
||||||
|
@ -991,6 +991,7 @@ static string readLine(int fd)
|
||||||
{
|
{
|
||||||
string s;
|
string s;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
checkInterrupt();
|
||||||
char ch;
|
char ch;
|
||||||
ssize_t rd = read(fd, &ch, 1);
|
ssize_t rd = read(fd, &ch, 1);
|
||||||
if (rd == -1) {
|
if (rd == -1) {
|
||||||
|
@ -1018,6 +1019,7 @@ static void drain(int fd)
|
||||||
{
|
{
|
||||||
unsigned char buffer[1024];
|
unsigned char buffer[1024];
|
||||||
while (1) {
|
while (1) {
|
||||||
|
checkInterrupt();
|
||||||
ssize_t rd = read(fd, buffer, sizeof buffer);
|
ssize_t rd = read(fd, buffer, sizeof buffer);
|
||||||
if (rd == -1) {
|
if (rd == -1) {
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
|
@ -1124,6 +1126,7 @@ DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
||||||
|
|
||||||
/* parent */
|
/* parent */
|
||||||
pid.setSeparatePG(true);
|
pid.setSeparatePG(true);
|
||||||
|
pid.setKillSignal(SIGTERM);
|
||||||
logPipe.writeSide.close();
|
logPipe.writeSide.close();
|
||||||
worker.childStarted(shared_from_this(),
|
worker.childStarted(shared_from_this(),
|
||||||
pid, singleton<set<int> >(logPipe.readSide), false);
|
pid, singleton<set<int> >(logPipe.readSide), false);
|
||||||
|
@ -1139,7 +1142,7 @@ DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
||||||
try {
|
try {
|
||||||
reply = readLine(fromHook.readSide);
|
reply = readLine(fromHook.readSide);
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
drain(logPipe.readSide);
|
terminateBuildHook(true);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1147,7 +1150,6 @@ DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
||||||
|
|
||||||
if (reply == "decline" || reply == "postpone") {
|
if (reply == "decline" || reply == "postpone") {
|
||||||
/* Clean up the child. !!! hacky / should verify */
|
/* Clean up the child. !!! hacky / should verify */
|
||||||
drain(logPipe.readSide);
|
|
||||||
terminateBuildHook();
|
terminateBuildHook();
|
||||||
return reply == "decline" ? rpDecline : rpPostpone;
|
return reply == "decline" ? rpDecline : rpPostpone;
|
||||||
}
|
}
|
||||||
|
@ -1215,18 +1217,22 @@ DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DerivationGoal::terminateBuildHook()
|
void DerivationGoal::terminateBuildHook(bool kill)
|
||||||
{
|
{
|
||||||
/* !!! drain stdout of hook */
|
/* !!! drain stdout of hook */
|
||||||
debug("terminating build hook");
|
debug("terminating build hook");
|
||||||
pid_t savedPid = pid;
|
pid_t savedPid = pid;
|
||||||
|
if (kill)
|
||||||
|
pid.kill();
|
||||||
|
else
|
||||||
pid.wait(true);
|
pid.wait(true);
|
||||||
/* `false' means don't wake up waiting goals, since we want to
|
/* `false' means don't wake up waiting goals, since we want to
|
||||||
keep this build slot ourselves (at least if the hook reply XXX. */
|
keep this build slot ourselves. */
|
||||||
worker.childTerminated(savedPid, false);
|
worker.childTerminated(savedPid, false);
|
||||||
fromHook.readSide.close();
|
fromHook.readSide.close();
|
||||||
toHook.writeSide.close();
|
toHook.writeSide.close();
|
||||||
fdLogFile.close();
|
fdLogFile.close();
|
||||||
|
drain(logPipe.readSide);
|
||||||
logPipe.readSide.close();
|
logPipe.readSide.close();
|
||||||
deleteTmpDir(true); /* get rid of the hook's temporary directory */
|
deleteTmpDir(true); /* get rid of the hook's temporary directory */
|
||||||
}
|
}
|
||||||
|
@ -2048,6 +2054,7 @@ void SubstitutionGoal::tryToRun()
|
||||||
|
|
||||||
/* parent */
|
/* parent */
|
||||||
pid.setSeparatePG(true);
|
pid.setSeparatePG(true);
|
||||||
|
pid.setKillSignal(SIGTERM);
|
||||||
logPipe.writeSide.close();
|
logPipe.writeSide.close();
|
||||||
worker.childStarted(shared_from_this(),
|
worker.childStarted(shared_from_this(),
|
||||||
pid, singleton<set<int> >(logPipe.readSide), true);
|
pid, singleton<set<int> >(logPipe.readSide), true);
|
||||||
|
|
|
@ -641,6 +641,7 @@ Pid::Pid()
|
||||||
{
|
{
|
||||||
pid = -1;
|
pid = -1;
|
||||||
separatePG = false;
|
separatePG = false;
|
||||||
|
killSignal = SIGKILL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -654,6 +655,7 @@ void Pid::operator =(pid_t pid)
|
||||||
{
|
{
|
||||||
if (this->pid != pid) kill();
|
if (this->pid != pid) kill();
|
||||||
this->pid = pid;
|
this->pid = pid;
|
||||||
|
killSignal = SIGKILL; // reset signal to default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -669,10 +671,10 @@ void Pid::kill()
|
||||||
|
|
||||||
printMsg(lvlError, format("killing process %1%") % pid);
|
printMsg(lvlError, format("killing process %1%") % pid);
|
||||||
|
|
||||||
/* Send a KILL signal to the child. If it has its own process
|
/* Send the requested signal to the child. If it has its own
|
||||||
group, send the signal to every process in the child process
|
process group, send the signal to every process in the child
|
||||||
group (which hopefully includes *all* its children). */
|
process group (which hopefully includes *all* its children). */
|
||||||
if (::kill(separatePG ? -pid : pid, SIGKILL) != 0)
|
if (::kill(separatePG ? -pid : pid, killSignal) != 0)
|
||||||
printMsg(lvlError, (SysError(format("killing process %1%") % pid).msg()));
|
printMsg(lvlError, (SysError(format("killing process %1%") % pid).msg()));
|
||||||
|
|
||||||
/* Wait until the child dies, disregarding the exit status. */
|
/* Wait until the child dies, disregarding the exit status. */
|
||||||
|
@ -710,6 +712,12 @@ void Pid::setSeparatePG(bool separatePG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Pid::setKillSignal(int signal)
|
||||||
|
{
|
||||||
|
this->killSignal = signal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void killUser(uid_t uid)
|
void killUser(uid_t uid)
|
||||||
{
|
{
|
||||||
debug(format("killing all processes running under uid `%1%'") % uid);
|
debug(format("killing all processes running under uid `%1%'") % uid);
|
||||||
|
|
|
@ -213,6 +213,7 @@ class Pid
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
bool separatePG;
|
bool separatePG;
|
||||||
|
int killSignal;
|
||||||
public:
|
public:
|
||||||
Pid();
|
Pid();
|
||||||
~Pid();
|
~Pid();
|
||||||
|
@ -221,6 +222,7 @@ public:
|
||||||
void kill();
|
void kill();
|
||||||
int wait(bool block);
|
int wait(bool block);
|
||||||
void setSeparatePG(bool separatePG);
|
void setSeparatePG(bool separatePG);
|
||||||
|
void setKillSignal(int signal);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue