diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2004-06-22T09·51+0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2004-06-22T09·51+0000 |
commit | c9fbd2dfd51eebcb561f9b548c10c68ad89652e5 (patch) | |
tree | 623a3303d6ad1bb4af9c7b63754f2693af895e16 /src/libstore | |
parent | 155d7c8dfa46da054beaf37d6415d52613e2bb17 (diff) |
* Wrapper class around pids.
Diffstat (limited to 'src/libstore')
-rw-r--r-- | src/libstore/normalise.cc | 100 | ||||
-rw-r--r-- | src/libstore/store.cc | 24 |
2 files changed, 37 insertions, 87 deletions
diff --git a/src/libstore/normalise.cc b/src/libstore/normalise.cc index 5d68945b07f7..9aeea119147f 100644 --- a/src/libstore/normalise.cc +++ b/src/libstore/normalise.cc @@ -3,11 +3,8 @@ #include <boost/enable_shared_from_this.hpp> #include <sys/types.h> -#include <sys/wait.h> #include <sys/stat.h> -#include <sys/time.h> #include <fcntl.h> -#include <signal.h> #include <unistd.h> #include "normalise.hh" @@ -60,7 +57,7 @@ protected: virtual ~Goal() { - debug("goal destroyed"); + printMsg(lvlVomit, "goal destroyed"); } public: @@ -160,26 +157,6 @@ public: ////////////////////////////////////////////////////////////////////// -void killChild(pid_t pid) -{ - /* Send a KILL signal to every process in the child process group - (which hopefully includes *all* its children). */ - if (kill(-pid, SIGKILL) != 0) - printMsg(lvlError, format("killing process %1%") % pid); - else { - /* Wait until the child dies, disregarding the exit status. */ - int status; - while (waitpid(pid, &status, 0) == -1) - if (errno != EINTR) printMsg(lvlError, - format("waiting for process %1%") % pid); - } -} - - - -////////////////////////////////////////////////////////////////////// - - void Goal::addWaiter(GoalPtr waiter) { waiters.insert(waiter); @@ -233,7 +210,7 @@ private: map<Path, Path> inputSucs; /* The process ID of the builder. */ - pid_t pid; + Pid pid; /* The temporary directory. */ Path tmpDir; @@ -309,7 +286,6 @@ NormalisationGoal::NormalisationGoal(const Path & _nePath, Worker & _worker) : Goal(_worker) { nePath = _nePath; - pid = -1; state = &NormalisationGoal::init; } @@ -318,13 +294,6 @@ NormalisationGoal::~NormalisationGoal() { /* Careful: we should never ever throw an exception from a destructor. */ - - if (pid != -1) { - printMsg(lvlError, format("killing child process %1% (%2%)") - % pid % nePath); - killChild(pid); - } - try { deleteTmpDir(false); } catch (Error & e) { @@ -471,20 +440,16 @@ void NormalisationGoal::buildDone() { debug(format("build done for `%1%'") % nePath); - int status; - /* Since we got an EOF on the logger pipe, the builder is presumed to have terminated. In fact, the builder could also have simply have closed its end of the pipe --- just don't do that :-) */ /* !!! this could block! */ - if (waitpid(pid, &status, 0) != pid) - throw SysError(format("builder for `%1%' should have terminated") - % nePath); + pid_t savedPid = pid; + int status = pid.wait(true); /* So the child is gone now. */ - worker.childTerminated(pid); - pid = -1; + worker.childTerminated(savedPid); /* Close the read side of the logger pipe. */ logPipe.readSide.close(); @@ -570,7 +535,8 @@ NormalisationGoal::HookReply NormalisationGoal::tryBuildHook() fromHook.create(); /* Fork the hook. */ - switch (pid = fork()) { + pid = fork(); + switch (pid) { case -1: throw SysError("unable to fork"); @@ -678,11 +644,9 @@ void NormalisationGoal::terminateBuildHook() { /* !!! drain stdout of hook */ debug("terminating build hook"); - int status; - if (waitpid(pid, &status, 0) != pid) - printMsg(lvlError, format("process `%1%' missing") % pid); - worker.childTerminated(pid); - pid = -1; + pid_t savedPid = pid; + pid.wait(true); + worker.childTerminated(savedPid); fromHook.readSide.close(); toHook.writeSide.close(); fdLogFile.close(); @@ -836,7 +800,8 @@ void NormalisationGoal::startBuilder() currently use forks to run and wait for the children, it shouldn't be hard to use threads for this on systems where fork() is unavailable or inefficient. */ - switch (pid = fork()) { + pid = fork(); + switch (pid) { case -1: throw SysError("unable to fork"); @@ -885,6 +850,7 @@ void NormalisationGoal::startBuilder() } /* parent */ + pid.setSeparatePG(true); logPipe.writeSide.close(); worker.childStarted(shared_from_this(), pid, logPipe.readSide, true); @@ -1199,7 +1165,7 @@ private: Pipe logPipe; /* The process ID of the builder. */ - pid_t pid; + Pid pid; /* Lock on the store path. */ PathLocks outputLock; @@ -1209,7 +1175,6 @@ private: public: SubstitutionGoal(const Path & _nePath, Worker & _worker); - ~SubstitutionGoal(); void work(); @@ -1227,22 +1192,10 @@ SubstitutionGoal::SubstitutionGoal(const Path & _storePath, Worker & _worker) : Goal(_worker) { storePath = _storePath; - pid = -1; state = &SubstitutionGoal::init; } -SubstitutionGoal::~SubstitutionGoal() -{ - /* !!! turn this into a destructor for pids */ - if (pid != -1) { - printMsg(lvlError, format("killing child process %1% (%2%)") - % pid % storePath); - killChild(pid); - } -} - - void SubstitutionGoal::work() { (this->*state)(); @@ -1345,7 +1298,8 @@ void SubstitutionGoal::tryToRun() deletePath(storePath); /* Fork the substitute program. */ - switch (pid = fork()) { + pid = fork(); + switch (pid) { case -1: throw SysError("unable to fork"); @@ -1402,6 +1356,7 @@ void SubstitutionGoal::tryToRun() } /* parent */ + pid.setSeparatePG(true); logPipe.writeSide.close(); worker.childStarted(shared_from_this(), pid, logPipe.readSide, true); @@ -1414,18 +1369,14 @@ void SubstitutionGoal::finished() { debug(format("substitute finished of `%1%'") % storePath); - int status; - /* Since we got an EOF on the logger pipe, the substitute is presumed to have terminated. */ /* !!! this could block! */ - if (waitpid(pid, &status, 0) != pid) - throw SysError(format("substitute for `%1%' should have terminated") - % storePath); + pid_t savedPid = pid; + int status = pid.wait(true); /* So the child is gone now. */ - worker.childTerminated(pid); - pid = -1; + worker.childTerminated(savedPid); /* Close the read side of the logger pipe. */ logPipe.readSide.close(); @@ -1534,7 +1485,7 @@ void Worker::removeGoal(GoalPtr goal) void Worker::wakeUp(GoalPtr goal) { - debug("wake up"); + printMsg(lvlVomit, "wake up"); awake.insert(goal); } @@ -1593,8 +1544,6 @@ void Worker::run() while (1) { - debug(format("main loop (%1% goals left)") % goals.size()); - checkInterrupt(); /* Call every wake goal. */ @@ -1602,7 +1551,8 @@ void Worker::run() Goals awake2(awake); /* !!! why is this necessary? */ awake.clear(); for (Goals::iterator i = awake2.begin(); i != awake2.end(); ++i) { - debug("goal"); + printMsg(lvlVomit, + format("running goal (%1% left)") % goals.size()); checkInterrupt(); GoalPtr goal = *i; goal->work(); @@ -1714,5 +1664,7 @@ void ensurePath(const Path & path) /* If the path is already valid, we're done. */ if (isValidPath(path)) return; - /* !!! add realisation goal */ + Worker worker; + worker.addSubstitutionGoal(path, GoalPtr()); + worker.run(); } diff --git a/src/libstore/store.cc b/src/libstore/store.cc index 59d4430fd692..2ec93d63bcbc 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -127,21 +127,22 @@ void copyPath(const Path & src, const Path & dst) use a thread). */ /* Create a pipe. */ - int fds[2]; - if (pipe(fds) == -1) throw SysError("creating pipe"); + Pipe pipe; + pipe.create(); /* Fork. */ - pid_t pid; - switch (pid = fork()) { + Pid pid; + pid = fork(); + switch (pid) { case -1: throw SysError("unable to fork"); case 0: /* child */ try { - close(fds[1]); + pipe.writeSide.close(); CopySource source; - source.fd = fds[0]; + source.fd = pipe.readSide; restorePath(dst, source); _exit(0); } catch (exception & e) { @@ -150,19 +151,16 @@ void copyPath(const Path & src, const Path & dst) _exit(1); } - close(fds[0]); - /* Parent. */ + pipe.readSide.close(); + CopySink sink; - sink.fd = fds[1]; + sink.fd = pipe.writeSide; dumpPath(src, sink); /* Wait for the child to finish. */ - int status; - if (waitpid(pid, &status, 0) != pid) - throw SysError("waiting for child"); - + int status = pid.wait(true); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) throw Error(format("cannot copy `%1% to `%2%': child %3%") % src % dst % statusToString(status)); |