Modernize AutoCloseFD
This commit is contained in:
parent
8a41792d43
commit
cb5e7254b6
11 changed files with 139 additions and 153 deletions
|
@ -325,7 +325,7 @@ RunPager::RunPager()
|
||||||
toPager.create();
|
toPager.create();
|
||||||
|
|
||||||
pid = startProcess([&]() {
|
pid = startProcess([&]() {
|
||||||
if (dup2(toPager.readSide, STDIN_FILENO) == -1)
|
if (dup2(toPager.readSide.get(), STDIN_FILENO) == -1)
|
||||||
throw SysError("dupping stdin");
|
throw SysError("dupping stdin");
|
||||||
if (!getenv("LESS"))
|
if (!getenv("LESS"))
|
||||||
setenv("LESS", "FRSXMK", 1);
|
setenv("LESS", "FRSXMK", 1);
|
||||||
|
@ -337,7 +337,7 @@ RunPager::RunPager()
|
||||||
throw SysError(format("executing ‘%1%’") % pager);
|
throw SysError(format("executing ‘%1%’") % pager);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (dup2(toPager.writeSide, STDOUT_FILENO) == -1)
|
if (dup2(toPager.writeSide.get(), STDOUT_FILENO) == -1)
|
||||||
throw SysError("dupping stdout");
|
throw SysError("dupping stdout");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -403,7 +403,7 @@ static void commonChildInit(Pipe & logPipe)
|
||||||
throw SysError(format("creating a new session"));
|
throw SysError(format("creating a new session"));
|
||||||
|
|
||||||
/* Dup the write side of the logger pipe into stderr. */
|
/* Dup the write side of the logger pipe into stderr. */
|
||||||
if (dup2(logPipe.writeSide, STDERR_FILENO) == -1)
|
if (dup2(logPipe.writeSide.get(), STDERR_FILENO) == -1)
|
||||||
throw SysError("cannot pipe standard error into log file");
|
throw SysError("cannot pipe standard error into log file");
|
||||||
|
|
||||||
/* Dup stderr to stdout. */
|
/* Dup stderr to stdout. */
|
||||||
|
@ -510,11 +510,11 @@ void UserLock::acquire()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
||||||
if (fd == -1)
|
if (!fd)
|
||||||
throw SysError(format("opening user lock ‘%1%’") % fnUserLock);
|
throw SysError(format("opening user lock ‘%1%’") % fnUserLock);
|
||||||
|
|
||||||
if (lockFile(fd, ltWrite, false)) {
|
if (lockFile(fd.get(), ltWrite, false)) {
|
||||||
fdUserLock = fd.borrow();
|
fdUserLock = std::move(fd);
|
||||||
lockedPaths.insert(fnUserLock);
|
lockedPaths.insert(fnUserLock);
|
||||||
user = i;
|
user = i;
|
||||||
uid = pw->pw_uid;
|
uid = pw->pw_uid;
|
||||||
|
@ -550,7 +550,7 @@ void UserLock::acquire()
|
||||||
void UserLock::release()
|
void UserLock::release()
|
||||||
{
|
{
|
||||||
if (uid == 0) return;
|
if (uid == 0) return;
|
||||||
fdUserLock.close(); /* releases lock */
|
fdUserLock = -1; /* releases lock */
|
||||||
assert(lockedPaths.find(fnUserLock) != lockedPaths.end());
|
assert(lockedPaths.find(fnUserLock) != lockedPaths.end());
|
||||||
lockedPaths.erase(fnUserLock);
|
lockedPaths.erase(fnUserLock);
|
||||||
fnUserLock = "";
|
fnUserLock = "";
|
||||||
|
@ -613,11 +613,11 @@ HookInstance::HookInstance()
|
||||||
if (chdir("/") == -1) throw SysError("changing into /");
|
if (chdir("/") == -1) throw SysError("changing into /");
|
||||||
|
|
||||||
/* Dup the communication pipes. */
|
/* Dup the communication pipes. */
|
||||||
if (dup2(toHook.readSide, STDIN_FILENO) == -1)
|
if (dup2(toHook.readSide.get(), STDIN_FILENO) == -1)
|
||||||
throw SysError("dupping to-hook read side");
|
throw SysError("dupping to-hook read side");
|
||||||
|
|
||||||
/* Use fd 4 for the builder's stdout/stderr. */
|
/* Use fd 4 for the builder's stdout/stderr. */
|
||||||
if (dup2(builderOut.writeSide, 4) == -1)
|
if (dup2(builderOut.writeSide.get(), 4) == -1)
|
||||||
throw SysError("dupping builder's stdout/stderr");
|
throw SysError("dupping builder's stdout/stderr");
|
||||||
|
|
||||||
Strings args = {
|
Strings args = {
|
||||||
|
@ -633,15 +633,15 @@ HookInstance::HookInstance()
|
||||||
});
|
});
|
||||||
|
|
||||||
pid.setSeparatePG(true);
|
pid.setSeparatePG(true);
|
||||||
fromHook.writeSide.close();
|
fromHook.writeSide = -1;
|
||||||
toHook.readSide.close();
|
toHook.readSide = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HookInstance::~HookInstance()
|
HookInstance::~HookInstance()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
toHook.writeSide.close();
|
toHook.writeSide = -1;
|
||||||
pid.kill(true);
|
pid.kill(true);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
ignoreException();
|
ignoreException();
|
||||||
|
@ -1414,10 +1414,10 @@ void DerivationGoal::buildDone()
|
||||||
|
|
||||||
/* Close the read side of the logger pipe. */
|
/* Close the read side of the logger pipe. */
|
||||||
if (hook) {
|
if (hook) {
|
||||||
hook->builderOut.readSide.close();
|
hook->builderOut.readSide = -1;
|
||||||
hook->fromHook.readSide.close();
|
hook->fromHook.readSide = -1;
|
||||||
}
|
}
|
||||||
else builderOut.readSide.close();
|
else builderOut.readSide = -1;
|
||||||
|
|
||||||
/* Close the log file. */
|
/* Close the log file. */
|
||||||
closeLogFile();
|
closeLogFile();
|
||||||
|
@ -1557,7 +1557,7 @@ HookReply DerivationGoal::tryBuildHook()
|
||||||
for (auto & i : features) checkStoreName(i); /* !!! abuse */
|
for (auto & i : features) checkStoreName(i); /* !!! abuse */
|
||||||
|
|
||||||
/* Send the request to the hook. */
|
/* Send the request to the hook. */
|
||||||
writeLine(worker.hook->toHook.writeSide, (format("%1% %2% %3% %4%")
|
writeLine(worker.hook->toHook.writeSide.get(), (format("%1% %2% %3% %4%")
|
||||||
% (worker.getNrLocalBuilds() < settings.maxBuildJobs ? "1" : "0")
|
% (worker.getNrLocalBuilds() < settings.maxBuildJobs ? "1" : "0")
|
||||||
% drv->platform % drvPath % concatStringsSep(",", features)).str());
|
% drv->platform % drvPath % concatStringsSep(",", features)).str());
|
||||||
|
|
||||||
|
@ -1565,7 +1565,7 @@ HookReply DerivationGoal::tryBuildHook()
|
||||||
whether the hook wishes to perform the build. */
|
whether the hook wishes to perform the build. */
|
||||||
string reply;
|
string reply;
|
||||||
while (true) {
|
while (true) {
|
||||||
string s = readLine(worker.hook->fromHook.readSide);
|
string s = readLine(worker.hook->fromHook.readSide.get());
|
||||||
if (string(s, 0, 2) == "# ") {
|
if (string(s, 0, 2) == "# ") {
|
||||||
reply = string(s, 2);
|
reply = string(s, 2);
|
||||||
break;
|
break;
|
||||||
|
@ -1597,22 +1597,22 @@ HookReply DerivationGoal::tryBuildHook()
|
||||||
|
|
||||||
string s;
|
string s;
|
||||||
for (auto & i : allInputs) { s += i; s += ' '; }
|
for (auto & i : allInputs) { s += i; s += ' '; }
|
||||||
writeLine(hook->toHook.writeSide, s);
|
writeLine(hook->toHook.writeSide.get(), s);
|
||||||
|
|
||||||
/* Tell the hooks the missing outputs that have to be copied back
|
/* Tell the hooks the missing outputs that have to be copied back
|
||||||
from the remote system. */
|
from the remote system. */
|
||||||
s = "";
|
s = "";
|
||||||
for (auto & i : missingPaths) { s += i; s += ' '; }
|
for (auto & i : missingPaths) { s += i; s += ' '; }
|
||||||
writeLine(hook->toHook.writeSide, s);
|
writeLine(hook->toHook.writeSide.get(), s);
|
||||||
|
|
||||||
hook->toHook.writeSide.close();
|
hook->toHook.writeSide = -1;
|
||||||
|
|
||||||
/* Create the log file and pipe. */
|
/* Create the log file and pipe. */
|
||||||
Path logFile = openLogFile();
|
Path logFile = openLogFile();
|
||||||
|
|
||||||
set<int> fds;
|
set<int> fds;
|
||||||
fds.insert(hook->fromHook.readSide);
|
fds.insert(hook->fromHook.readSide.get());
|
||||||
fds.insert(hook->builderOut.readSide);
|
fds.insert(hook->builderOut.readSide.get());
|
||||||
worker.childStarted(shared_from_this(), fds, false, false);
|
worker.childStarted(shared_from_this(), fds, false, false);
|
||||||
|
|
||||||
return rpAccept;
|
return rpAccept;
|
||||||
|
@ -2142,17 +2142,17 @@ void DerivationGoal::startBuilder()
|
||||||
child = clone(childEntry, stack + stackSize, flags & ~CLONE_NEWPID, this);
|
child = clone(childEntry, stack + stackSize, flags & ~CLONE_NEWPID, this);
|
||||||
if (child == -1) throw SysError("cloning builder process");
|
if (child == -1) throw SysError("cloning builder process");
|
||||||
|
|
||||||
writeFull(builderOut.writeSide, std::to_string(child) + "\n");
|
writeFull(builderOut.writeSide.get(), std::to_string(child) + "\n");
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
if (helper.wait(true) != 0)
|
if (helper.wait(true) != 0)
|
||||||
throw Error("unable to start build process");
|
throw Error("unable to start build process");
|
||||||
|
|
||||||
userNamespaceSync.readSide.close();
|
userNamespaceSync.readSide = -1;
|
||||||
|
|
||||||
pid_t tmp;
|
pid_t tmp;
|
||||||
if (!string2Int<pid_t>(readLine(builderOut.readSide), tmp)) abort();
|
if (!string2Int<pid_t>(readLine(builderOut.readSide.get()), tmp)) abort();
|
||||||
pid = tmp;
|
pid = tmp;
|
||||||
|
|
||||||
/* Set the UID/GID mapping of the builder's user
|
/* Set the UID/GID mapping of the builder's user
|
||||||
|
@ -2171,8 +2171,8 @@ void DerivationGoal::startBuilder()
|
||||||
|
|
||||||
/* Signal the builder that we've updated its user
|
/* Signal the builder that we've updated its user
|
||||||
namespace. */
|
namespace. */
|
||||||
writeFull(userNamespaceSync.writeSide, "1");
|
writeFull(userNamespaceSync.writeSide.get(), "1");
|
||||||
userNamespaceSync.writeSide.close();
|
userNamespaceSync.writeSide = -1;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -2186,12 +2186,12 @@ void DerivationGoal::startBuilder()
|
||||||
|
|
||||||
/* parent */
|
/* parent */
|
||||||
pid.setSeparatePG(true);
|
pid.setSeparatePG(true);
|
||||||
builderOut.writeSide.close();
|
builderOut.writeSide = -1;
|
||||||
worker.childStarted(shared_from_this(), {builderOut.readSide}, true, true);
|
worker.childStarted(shared_from_this(), {builderOut.readSide.get()}, true, true);
|
||||||
|
|
||||||
/* Check if setting up the build environment failed. */
|
/* Check if setting up the build environment failed. */
|
||||||
while (true) {
|
while (true) {
|
||||||
string msg = readLine(builderOut.readSide);
|
string msg = readLine(builderOut.readSide.get());
|
||||||
if (string(msg, 0, 1) == "\1") {
|
if (string(msg, 0, 1) == "\1") {
|
||||||
if (msg.size() == 1) break;
|
if (msg.size() == 1) break;
|
||||||
throw Error(string(msg, 1));
|
throw Error(string(msg, 1));
|
||||||
|
@ -2215,26 +2215,24 @@ void DerivationGoal::runChild()
|
||||||
#if __linux__
|
#if __linux__
|
||||||
if (useChroot) {
|
if (useChroot) {
|
||||||
|
|
||||||
userNamespaceSync.writeSide.close();
|
userNamespaceSync.writeSide = -1;
|
||||||
|
|
||||||
if (drainFD(userNamespaceSync.readSide) != "1")
|
if (drainFD(userNamespaceSync.readSide.get()) != "1")
|
||||||
throw Error("user namespace initialisation failed");
|
throw Error("user namespace initialisation failed");
|
||||||
|
|
||||||
userNamespaceSync.readSide.close();
|
userNamespaceSync.readSide = -1;
|
||||||
|
|
||||||
if (privateNetwork) {
|
if (privateNetwork) {
|
||||||
|
|
||||||
/* Initialise the loopback interface. */
|
/* Initialise the loopback interface. */
|
||||||
AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP));
|
AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP));
|
||||||
if (fd == -1) throw SysError("cannot open IP socket");
|
if (!fd) throw SysError("cannot open IP socket");
|
||||||
|
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
strcpy(ifr.ifr_name, "lo");
|
strcpy(ifr.ifr_name, "lo");
|
||||||
ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING;
|
ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING;
|
||||||
if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1)
|
if (ioctl(fd.get(), SIOCSIFFLAGS, &ifr) == -1)
|
||||||
throw SysError("cannot set loopback interface flags");
|
throw SysError("cannot set loopback interface flags");
|
||||||
|
|
||||||
fd.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the hostname etc. to fixed values. */
|
/* Set the hostname etc. to fixed values. */
|
||||||
|
@ -2919,9 +2917,9 @@ Path DerivationGoal::openLogFile()
|
||||||
% (settings.compressLog ? ".bz2" : "")).str();
|
% (settings.compressLog ? ".bz2" : "")).str();
|
||||||
|
|
||||||
fdLogFile = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0666);
|
fdLogFile = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0666);
|
||||||
if (fdLogFile == -1) throw SysError(format("creating log file ‘%1%’") % logFileName);
|
if (!fdLogFile) throw SysError(format("creating log file ‘%1%’") % logFileName);
|
||||||
|
|
||||||
logFileSink = std::make_shared<FdSink>(fdLogFile);
|
logFileSink = std::make_shared<FdSink>(fdLogFile.get());
|
||||||
|
|
||||||
if (settings.compressLog)
|
if (settings.compressLog)
|
||||||
logSink = std::shared_ptr<CompressionSink>(makeCompressionSink("bzip2", *logFileSink));
|
logSink = std::shared_ptr<CompressionSink>(makeCompressionSink("bzip2", *logFileSink));
|
||||||
|
@ -2938,7 +2936,7 @@ void DerivationGoal::closeLogFile()
|
||||||
if (logSink2) logSink2->finish();
|
if (logSink2) logSink2->finish();
|
||||||
if (logFileSink) logFileSink->flush();
|
if (logFileSink) logFileSink->flush();
|
||||||
logSink = logFileSink = 0;
|
logSink = logFileSink = 0;
|
||||||
fdLogFile.close();
|
fdLogFile = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2960,8 +2958,8 @@ void DerivationGoal::deleteTmpDir(bool force)
|
||||||
|
|
||||||
void DerivationGoal::handleChildOutput(int fd, const string & data)
|
void DerivationGoal::handleChildOutput(int fd, const string & data)
|
||||||
{
|
{
|
||||||
if ((hook && fd == hook->builderOut.readSide) ||
|
if ((hook && fd == hook->builderOut.readSide.get()) ||
|
||||||
(!hook && fd == builderOut.readSide))
|
(!hook && fd == builderOut.readSide.get()))
|
||||||
{
|
{
|
||||||
logSize += data.size();
|
logSize += data.size();
|
||||||
if (settings.maxLogSize && logSize > settings.maxLogSize) {
|
if (settings.maxLogSize && logSize > settings.maxLogSize) {
|
||||||
|
@ -2987,7 +2985,7 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
|
||||||
if (logSink) (*logSink)(data);
|
if (logSink) (*logSink)(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hook && fd == hook->fromHook.readSide)
|
if (hook && fd == hook->fromHook.readSide.get())
|
||||||
printMsg(lvlError, data); // FIXME?
|
printMsg(lvlError, data); // FIXME?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3274,7 +3272,7 @@ void SubstitutionGoal::tryToRun()
|
||||||
thr = std::thread([this]() {
|
thr = std::thread([this]() {
|
||||||
try {
|
try {
|
||||||
/* Wake up the worker loop when we're done. */
|
/* Wake up the worker loop when we're done. */
|
||||||
Finally updateStats([this]() { outPipe.writeSide.close(); });
|
Finally updateStats([this]() { outPipe.writeSide = -1; });
|
||||||
|
|
||||||
copyStorePath(ref<Store>(sub), ref<Store>(worker.store.shared_from_this()),
|
copyStorePath(ref<Store>(sub), ref<Store>(worker.store.shared_from_this()),
|
||||||
storePath, repair);
|
storePath, repair);
|
||||||
|
@ -3285,7 +3283,7 @@ void SubstitutionGoal::tryToRun()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
worker.childStarted(shared_from_this(), {outPipe.readSide}, true, false);
|
worker.childStarted(shared_from_this(), {outPipe.readSide.get()}, true, false);
|
||||||
|
|
||||||
state = &SubstitutionGoal::finished;
|
state = &SubstitutionGoal::finished;
|
||||||
}
|
}
|
||||||
|
@ -3325,7 +3323,7 @@ void SubstitutionGoal::handleChildOutput(int fd, const string & data)
|
||||||
|
|
||||||
void SubstitutionGoal::handleEOF(int fd)
|
void SubstitutionGoal::handleEOF(int fd)
|
||||||
{
|
{
|
||||||
if (fd == outPipe.readSide) worker.wakeUp(shared_from_this());
|
if (fd == outPipe.readSide.get()) worker.wakeUp(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,19 +34,19 @@ int LocalStore::openGCLock(LockType lockType)
|
||||||
debug(format("acquiring global GC lock ‘%1%’") % fnGCLock);
|
debug(format("acquiring global GC lock ‘%1%’") % fnGCLock);
|
||||||
|
|
||||||
AutoCloseFD fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
AutoCloseFD fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
||||||
if (fdGCLock == -1)
|
if (!fdGCLock)
|
||||||
throw SysError(format("opening global GC lock ‘%1%’") % fnGCLock);
|
throw SysError(format("opening global GC lock ‘%1%’") % fnGCLock);
|
||||||
|
|
||||||
if (!lockFile(fdGCLock, lockType, false)) {
|
if (!lockFile(fdGCLock.get(), lockType, false)) {
|
||||||
printMsg(lvlError, format("waiting for the big garbage collector lock..."));
|
printMsg(lvlError, format("waiting for the big garbage collector lock..."));
|
||||||
lockFile(fdGCLock, lockType, true);
|
lockFile(fdGCLock.get(), lockType, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* !!! Restrict read permission on the GC root. Otherwise any
|
/* !!! Restrict read permission on the GC root. Otherwise any
|
||||||
process that can open the file for reading can DoS the
|
process that can open the file for reading can DoS the
|
||||||
collector. */
|
collector. */
|
||||||
|
|
||||||
return fdGCLock.borrow();
|
return fdGCLock.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ void LocalStore::addTempRoot(const Path & path)
|
||||||
auto state(_state.lock());
|
auto state(_state.lock());
|
||||||
|
|
||||||
/* Create the temporary roots file for this process. */
|
/* Create the temporary roots file for this process. */
|
||||||
if (state->fdTempRoots == -1) {
|
if (!state->fdTempRoots) {
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
Path dir = (format("%1%/%2%") % stateDir % tempRootsDir).str();
|
Path dir = (format("%1%/%2%") % stateDir % tempRootsDir).str();
|
||||||
|
@ -166,15 +166,15 @@ void LocalStore::addTempRoot(const Path & path)
|
||||||
|
|
||||||
state->fdTempRoots = openLockFile(state->fnTempRoots, true);
|
state->fdTempRoots = openLockFile(state->fnTempRoots, true);
|
||||||
|
|
||||||
fdGCLock.close();
|
fdGCLock = -1;
|
||||||
|
|
||||||
debug(format("acquiring read lock on ‘%1%’") % state->fnTempRoots);
|
debug(format("acquiring read lock on ‘%1%’") % state->fnTempRoots);
|
||||||
lockFile(state->fdTempRoots, ltRead, true);
|
lockFile(state->fdTempRoots.get(), ltRead, true);
|
||||||
|
|
||||||
/* Check whether the garbage collector didn't get in our
|
/* Check whether the garbage collector didn't get in our
|
||||||
way. */
|
way. */
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (fstat(state->fdTempRoots, &st) == -1)
|
if (fstat(state->fdTempRoots.get(), &st) == -1)
|
||||||
throw SysError(format("statting ‘%1%’") % state->fnTempRoots);
|
throw SysError(format("statting ‘%1%’") % state->fnTempRoots);
|
||||||
if (st.st_size == 0) break;
|
if (st.st_size == 0) break;
|
||||||
|
|
||||||
|
@ -188,14 +188,14 @@ void LocalStore::addTempRoot(const Path & path)
|
||||||
/* Upgrade the lock to a write lock. This will cause us to block
|
/* Upgrade the lock to a write lock. This will cause us to block
|
||||||
if the garbage collector is holding our lock. */
|
if the garbage collector is holding our lock. */
|
||||||
debug(format("acquiring write lock on ‘%1%’") % state->fnTempRoots);
|
debug(format("acquiring write lock on ‘%1%’") % state->fnTempRoots);
|
||||||
lockFile(state->fdTempRoots, ltWrite, true);
|
lockFile(state->fdTempRoots.get(), ltWrite, true);
|
||||||
|
|
||||||
string s = path + '\0';
|
string s = path + '\0';
|
||||||
writeFull(state->fdTempRoots, s);
|
writeFull(state->fdTempRoots.get(), s);
|
||||||
|
|
||||||
/* Downgrade to a read lock. */
|
/* Downgrade to a read lock. */
|
||||||
debug(format("downgrading to read lock on ‘%1%’") % state->fnTempRoots);
|
debug(format("downgrading to read lock on ‘%1%’") % state->fnTempRoots);
|
||||||
lockFile(state->fdTempRoots, ltRead, true);
|
lockFile(state->fdTempRoots.get(), ltRead, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds)
|
||||||
|
|
||||||
debug(format("reading temporary root file ‘%1%’") % path);
|
debug(format("reading temporary root file ‘%1%’") % path);
|
||||||
FDPtr fd(new AutoCloseFD(open(path.c_str(), O_CLOEXEC | O_RDWR, 0666)));
|
FDPtr fd(new AutoCloseFD(open(path.c_str(), O_CLOEXEC | O_RDWR, 0666)));
|
||||||
if (*fd == -1) {
|
if (!*fd) {
|
||||||
/* It's okay if the file has disappeared. */
|
/* It's okay if the file has disappeared. */
|
||||||
if (errno == ENOENT) continue;
|
if (errno == ENOENT) continue;
|
||||||
throw SysError(format("opening temporary roots file ‘%1%’") % path);
|
throw SysError(format("opening temporary roots file ‘%1%’") % path);
|
||||||
|
@ -224,10 +224,10 @@ void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds)
|
||||||
/* Try to acquire a write lock without blocking. This can
|
/* Try to acquire a write lock without blocking. This can
|
||||||
only succeed if the owning process has died. In that case
|
only succeed if the owning process has died. In that case
|
||||||
we don't care about its temporary roots. */
|
we don't care about its temporary roots. */
|
||||||
if (lockFile(*fd, ltWrite, false)) {
|
if (lockFile(fd->get(), ltWrite, false)) {
|
||||||
printMsg(lvlError, format("removing stale temporary roots file ‘%1%’") % path);
|
printMsg(lvlError, format("removing stale temporary roots file ‘%1%’") % path);
|
||||||
unlink(path.c_str());
|
unlink(path.c_str());
|
||||||
writeFull(*fd, "d");
|
writeFull(fd->get(), "d");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,10 +235,10 @@ void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds)
|
||||||
from upgrading to a write lock, therefore it will block in
|
from upgrading to a write lock, therefore it will block in
|
||||||
addTempRoot(). */
|
addTempRoot(). */
|
||||||
debug(format("waiting for read lock on ‘%1%’") % path);
|
debug(format("waiting for read lock on ‘%1%’") % path);
|
||||||
lockFile(*fd, ltRead, true);
|
lockFile(fd->get(), ltRead, true);
|
||||||
|
|
||||||
/* Read the entire file. */
|
/* Read the entire file. */
|
||||||
string contents = readFile(*fd);
|
string contents = readFile(fd->get());
|
||||||
|
|
||||||
/* Extract the roots. */
|
/* Extract the roots. */
|
||||||
string::size_type pos = 0, end;
|
string::size_type pos = 0, end;
|
||||||
|
@ -721,7 +721,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow other processes to add to the store from here on. */
|
/* Allow other processes to add to the store from here on. */
|
||||||
fdGCLock.close();
|
fdGCLock = -1;
|
||||||
fds.clear();
|
fds.clear();
|
||||||
|
|
||||||
/* Delete the trash directory. */
|
/* Delete the trash directory. */
|
||||||
|
|
|
@ -120,11 +120,11 @@ LocalStore::LocalStore(const Params & params)
|
||||||
AutoCloseFD fd = open(reservedPath.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, 0600);
|
AutoCloseFD fd = open(reservedPath.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, 0600);
|
||||||
int res = -1;
|
int res = -1;
|
||||||
#if HAVE_POSIX_FALLOCATE
|
#if HAVE_POSIX_FALLOCATE
|
||||||
res = posix_fallocate(fd, 0, settings.reservedSize);
|
res = posix_fallocate(fd.get(), 0, settings.reservedSize);
|
||||||
#endif
|
#endif
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
writeFull(fd, string(settings.reservedSize, 'X'));
|
writeFull(fd.get(), string(settings.reservedSize, 'X'));
|
||||||
ftruncate(fd, settings.reservedSize);
|
ftruncate(fd.get(), settings.reservedSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SysError & e) { /* don't care about errors */
|
} catch (SysError & e) { /* don't care about errors */
|
||||||
|
@ -135,9 +135,9 @@ LocalStore::LocalStore(const Params & params)
|
||||||
Path globalLockPath = dbDir + "/big-lock";
|
Path globalLockPath = dbDir + "/big-lock";
|
||||||
globalLock = openLockFile(globalLockPath.c_str(), true);
|
globalLock = openLockFile(globalLockPath.c_str(), true);
|
||||||
|
|
||||||
if (!lockFile(globalLock, ltRead, false)) {
|
if (!lockFile(globalLock.get(), ltRead, false)) {
|
||||||
printMsg(lvlError, "waiting for the big Nix store lock...");
|
printMsg(lvlError, "waiting for the big Nix store lock...");
|
||||||
lockFile(globalLock, ltRead, true);
|
lockFile(globalLock.get(), ltRead, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the current database schema and if necessary do an
|
/* Check the current database schema and if necessary do an
|
||||||
|
@ -166,9 +166,9 @@ LocalStore::LocalStore(const Params & params)
|
||||||
"which is no longer supported. To convert to the new format,\n"
|
"which is no longer supported. To convert to the new format,\n"
|
||||||
"please upgrade Nix to version 1.11 first.");
|
"please upgrade Nix to version 1.11 first.");
|
||||||
|
|
||||||
if (!lockFile(globalLock, ltWrite, false)) {
|
if (!lockFile(globalLock.get(), ltWrite, false)) {
|
||||||
printMsg(lvlError, "waiting for exclusive access to the Nix store...");
|
printMsg(lvlError, "waiting for exclusive access to the Nix store...");
|
||||||
lockFile(globalLock, ltWrite, true);
|
lockFile(globalLock.get(), ltWrite, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the schema version again, because another process may
|
/* Get the schema version again, because another process may
|
||||||
|
@ -197,7 +197,7 @@ LocalStore::LocalStore(const Params & params)
|
||||||
|
|
||||||
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
|
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
|
||||||
|
|
||||||
lockFile(globalLock, ltRead, true);
|
lockFile(globalLock.get(), ltRead, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
else openDB(*state, false);
|
else openDB(*state, false);
|
||||||
|
@ -236,8 +236,8 @@ LocalStore::~LocalStore()
|
||||||
auto state(_state.lock());
|
auto state(_state.lock());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (state->fdTempRoots != -1) {
|
if (state->fdTempRoots) {
|
||||||
state->fdTempRoots.close();
|
state->fdTempRoots = -1;
|
||||||
unlink(state->fnTempRoots.c_str());
|
unlink(state->fnTempRoots.c_str());
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
@ -1115,7 +1115,7 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
|
||||||
|
|
||||||
/* Release the GC lock so that checking content hashes (which can
|
/* Release the GC lock so that checking content hashes (which can
|
||||||
take ages) doesn't block the GC or builds. */
|
take ages) doesn't block the GC or builds. */
|
||||||
fdGCLock.close();
|
fdGCLock = -1;
|
||||||
|
|
||||||
/* Optionally, check the content hashes (slow). */
|
/* Optionally, check the content hashes (slow). */
|
||||||
if (checkContents) {
|
if (checkContents) {
|
||||||
|
|
|
@ -17,10 +17,10 @@ int openLockFile(const Path & path, bool create)
|
||||||
AutoCloseFD fd;
|
AutoCloseFD fd;
|
||||||
|
|
||||||
fd = open(path.c_str(), O_CLOEXEC | O_RDWR | (create ? O_CREAT : 0), 0600);
|
fd = open(path.c_str(), O_CLOEXEC | O_RDWR | (create ? O_CREAT : 0), 0600);
|
||||||
if (fd == -1 && (create || errno != ENOENT))
|
if (!fd && (create || errno != ENOENT))
|
||||||
throw SysError(format("opening lock file ‘%1%’") % path);
|
throw SysError(format("opening lock file ‘%1%’") % path);
|
||||||
|
|
||||||
return fd.borrow();
|
return fd.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -119,10 +119,10 @@ bool PathLocks::lockPaths(const PathSet & _paths,
|
||||||
fd = openLockFile(lockPath, true);
|
fd = openLockFile(lockPath, true);
|
||||||
|
|
||||||
/* Acquire an exclusive lock. */
|
/* Acquire an exclusive lock. */
|
||||||
if (!lockFile(fd, ltWrite, false)) {
|
if (!lockFile(fd.get(), ltWrite, false)) {
|
||||||
if (wait) {
|
if (wait) {
|
||||||
if (waitMsg != "") printMsg(lvlError, waitMsg);
|
if (waitMsg != "") printMsg(lvlError, waitMsg);
|
||||||
lockFile(fd, ltWrite, true);
|
lockFile(fd.get(), ltWrite, true);
|
||||||
} else {
|
} else {
|
||||||
/* Failed to lock this path; release all other
|
/* Failed to lock this path; release all other
|
||||||
locks. */
|
locks. */
|
||||||
|
@ -136,7 +136,7 @@ bool PathLocks::lockPaths(const PathSet & _paths,
|
||||||
/* Check that the lock file hasn't become stale (i.e.,
|
/* Check that the lock file hasn't become stale (i.e.,
|
||||||
hasn't been unlinked). */
|
hasn't been unlinked). */
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (fstat(fd, &st) == -1)
|
if (fstat(fd.get(), &st) == -1)
|
||||||
throw SysError(format("statting lock file ‘%1%’") % lockPath);
|
throw SysError(format("statting lock file ‘%1%’") % lockPath);
|
||||||
if (st.st_size != 0)
|
if (st.st_size != 0)
|
||||||
/* This lock file has been unlinked, so we're holding
|
/* This lock file has been unlinked, so we're holding
|
||||||
|
@ -149,7 +149,7 @@ bool PathLocks::lockPaths(const PathSet & _paths,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use borrow so that the descriptor isn't closed. */
|
/* Use borrow so that the descriptor isn't closed. */
|
||||||
fds.push_back(FDPair(fd.borrow(), lockPath));
|
fds.push_back(FDPair(fd.release(), lockPath));
|
||||||
lockedPaths.insert(lockPath);
|
lockedPaths.insert(lockPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,9 +66,9 @@ ref<RemoteStore::Connection> RemoteStore::openConnection()
|
||||||
| SOCK_CLOEXEC
|
| SOCK_CLOEXEC
|
||||||
#endif
|
#endif
|
||||||
, 0);
|
, 0);
|
||||||
if (conn->fd == -1)
|
if (!conn->fd)
|
||||||
throw SysError("cannot create Unix domain socket");
|
throw SysError("cannot create Unix domain socket");
|
||||||
closeOnExec(conn->fd);
|
closeOnExec(conn->fd.get());
|
||||||
|
|
||||||
string socketPath = settings.nixDaemonSocketFile;
|
string socketPath = settings.nixDaemonSocketFile;
|
||||||
|
|
||||||
|
@ -78,11 +78,11 @@ ref<RemoteStore::Connection> RemoteStore::openConnection()
|
||||||
throw Error(format("socket path ‘%1%’ is too long") % socketPath);
|
throw Error(format("socket path ‘%1%’ is too long") % socketPath);
|
||||||
strcpy(addr.sun_path, socketPath.c_str());
|
strcpy(addr.sun_path, socketPath.c_str());
|
||||||
|
|
||||||
if (connect(conn->fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
if (connect(conn->fd.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||||
throw SysError(format("cannot connect to daemon at ‘%1%’") % socketPath);
|
throw SysError(format("cannot connect to daemon at ‘%1%’") % socketPath);
|
||||||
|
|
||||||
conn->from.fd = conn->fd;
|
conn->from.fd = conn->fd.get();
|
||||||
conn->to.fd = conn->fd;
|
conn->to.fd = conn->fd.get();
|
||||||
|
|
||||||
/* Send the magic greeting, check for the reply. */
|
/* Send the magic greeting, check for the reply. */
|
||||||
try {
|
try {
|
||||||
|
@ -531,7 +531,7 @@ RemoteStore::Connection::~Connection()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
to.flush();
|
to.flush();
|
||||||
fd.close();
|
fd = -1;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
ignoreException();
|
ignoreException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,14 +42,14 @@ static void dumpContents(const Path & path, size_t size,
|
||||||
sink << "contents" << size;
|
sink << "contents" << size;
|
||||||
|
|
||||||
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
|
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
|
||||||
if (fd == -1) throw SysError(format("opening file ‘%1%’") % path);
|
if (!fd) throw SysError(format("opening file ‘%1%’") % path);
|
||||||
|
|
||||||
unsigned char buf[65536];
|
unsigned char buf[65536];
|
||||||
size_t left = size;
|
size_t left = size;
|
||||||
|
|
||||||
while (left > 0) {
|
while (left > 0) {
|
||||||
size_t n = left > sizeof(buf) ? sizeof(buf) : left;
|
size_t n = left > sizeof(buf) ? sizeof(buf) : left;
|
||||||
readFull(fd, buf, n);
|
readFull(fd.get(), buf, n);
|
||||||
left -= n;
|
left -= n;
|
||||||
sink(buf, n);
|
sink(buf, n);
|
||||||
}
|
}
|
||||||
|
@ -303,17 +303,16 @@ struct RestoreSink : ParseSink
|
||||||
void createRegularFile(const Path & path)
|
void createRegularFile(const Path & path)
|
||||||
{
|
{
|
||||||
Path p = dstPath + path;
|
Path p = dstPath + path;
|
||||||
fd.close();
|
|
||||||
fd = open(p.c_str(), O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC, 0666);
|
fd = open(p.c_str(), O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC, 0666);
|
||||||
if (fd == -1) throw SysError(format("creating file ‘%1%’") % p);
|
if (!fd) throw SysError(format("creating file ‘%1%’") % p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isExecutable()
|
void isExecutable()
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (fstat(fd, &st) == -1)
|
if (fstat(fd.get(), &st) == -1)
|
||||||
throw SysError("fstat");
|
throw SysError("fstat");
|
||||||
if (fchmod(fd, st.st_mode | (S_IXUSR | S_IXGRP | S_IXOTH)) == -1)
|
if (fchmod(fd.get(), st.st_mode | (S_IXUSR | S_IXGRP | S_IXOTH)) == -1)
|
||||||
throw SysError("fchmod");
|
throw SysError("fchmod");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +320,7 @@ struct RestoreSink : ParseSink
|
||||||
{
|
{
|
||||||
#if HAVE_POSIX_FALLOCATE
|
#if HAVE_POSIX_FALLOCATE
|
||||||
if (len) {
|
if (len) {
|
||||||
errno = posix_fallocate(fd, 0, len);
|
errno = posix_fallocate(fd.get(), 0, len);
|
||||||
/* Note that EINVAL may indicate that the underlying
|
/* Note that EINVAL may indicate that the underlying
|
||||||
filesystem doesn't support preallocation (e.g. on
|
filesystem doesn't support preallocation (e.g. on
|
||||||
OpenSolaris). Since preallocation is just an
|
OpenSolaris). Since preallocation is just an
|
||||||
|
@ -334,7 +333,7 @@ struct RestoreSink : ParseSink
|
||||||
|
|
||||||
void receiveContents(unsigned char * data, unsigned int len)
|
void receiveContents(unsigned char * data, unsigned int len)
|
||||||
{
|
{
|
||||||
writeFull(fd, data, len);
|
writeFull(fd.get(), data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createSymlink(const Path & path, const string & target)
|
void createSymlink(const Path & path, const string & target)
|
||||||
|
|
|
@ -255,11 +255,11 @@ Hash hashFile(HashType ht, const Path & path)
|
||||||
start(ht, ctx);
|
start(ht, ctx);
|
||||||
|
|
||||||
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
|
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
|
||||||
if (fd == -1) throw SysError(format("opening file ‘%1%’") % path);
|
if (!fd) throw SysError(format("opening file ‘%1%’") % path);
|
||||||
|
|
||||||
unsigned char buf[8192];
|
unsigned char buf[8192];
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
while ((n = read(fd, buf, sizeof(buf)))) {
|
while ((n = read(fd.get(), buf, sizeof(buf)))) {
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
if (n == -1) throw SysError(format("reading file ‘%1%’") % path);
|
if (n == -1) throw SysError(format("reading file ‘%1%’") % path);
|
||||||
update(ht, ctx, buf, n);
|
update(ht, ctx, buf, n);
|
||||||
|
|
|
@ -274,18 +274,18 @@ string readFile(int fd)
|
||||||
string readFile(const Path & path, bool drain)
|
string readFile(const Path & path, bool drain)
|
||||||
{
|
{
|
||||||
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
|
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
|
||||||
if (fd == -1)
|
if (!fd)
|
||||||
throw SysError(format("opening file ‘%1%’") % path);
|
throw SysError(format("opening file ‘%1%’") % path);
|
||||||
return drain ? drainFD(fd) : readFile(fd);
|
return drain ? drainFD(fd.get()) : readFile(fd.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void writeFile(const Path & path, const string & s)
|
void writeFile(const Path & path, const string & s)
|
||||||
{
|
{
|
||||||
AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0666);
|
AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0666);
|
||||||
if (fd == -1)
|
if (!fd)
|
||||||
throw SysError(format("opening file ‘%1%’") % path);
|
throw SysError(format("opening file ‘%1%’") % path);
|
||||||
writeFull(fd, s);
|
writeFull(fd.get(), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -556,28 +556,24 @@ void AutoDelete::reset(const Path & p, bool recursive) {
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
AutoCloseFD::AutoCloseFD()
|
AutoCloseFD::AutoCloseFD() : fd{-1} {}
|
||||||
|
|
||||||
|
|
||||||
|
AutoCloseFD::AutoCloseFD(int fd) : fd{fd} {}
|
||||||
|
|
||||||
|
|
||||||
|
AutoCloseFD::AutoCloseFD(AutoCloseFD&& that) : fd{that.fd}
|
||||||
{
|
{
|
||||||
fd = -1;
|
that.fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AutoCloseFD::AutoCloseFD(int fd)
|
AutoCloseFD& AutoCloseFD::operator =(AutoCloseFD&& that)
|
||||||
{
|
{
|
||||||
this->fd = fd;
|
close();
|
||||||
}
|
fd = that.fd;
|
||||||
|
that.fd = -1;
|
||||||
|
return *this;
|
||||||
AutoCloseFD::AutoCloseFD(const AutoCloseFD & fd)
|
|
||||||
{
|
|
||||||
/* Copying an AutoCloseFD isn't allowed (who should get to close
|
|
||||||
it?). But as an edge case, allow copying of closed
|
|
||||||
AutoCloseFDs. This is necessary due to tiresome reasons
|
|
||||||
involving copy constructor use on default object values in STL
|
|
||||||
containers (like when you do `map[value]' where value isn't in
|
|
||||||
the map yet). */
|
|
||||||
this->fd = fd.fd;
|
|
||||||
if (this->fd != -1) abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -591,14 +587,7 @@ AutoCloseFD::~AutoCloseFD()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AutoCloseFD::operator =(int fd)
|
int AutoCloseFD::get() const
|
||||||
{
|
|
||||||
if (this->fd != fd) close();
|
|
||||||
this->fd = fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
AutoCloseFD::operator int() const
|
|
||||||
{
|
{
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -610,19 +599,17 @@ void AutoCloseFD::close()
|
||||||
if (::close(fd) == -1)
|
if (::close(fd) == -1)
|
||||||
/* This should never happen. */
|
/* This should never happen. */
|
||||||
throw SysError(format("closing file descriptor %1%") % fd);
|
throw SysError(format("closing file descriptor %1%") % fd);
|
||||||
fd = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AutoCloseFD::isOpen()
|
AutoCloseFD::operator bool() const
|
||||||
{
|
{
|
||||||
return fd != -1;
|
return fd != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Pass responsibility for closing this fd to the caller. */
|
int AutoCloseFD::release()
|
||||||
int AutoCloseFD::borrow()
|
|
||||||
{
|
{
|
||||||
int oldFD = fd;
|
int oldFD = fd;
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
@ -899,10 +886,10 @@ string runProgram(Path program, bool searchPath, const Strings & args,
|
||||||
|
|
||||||
/* Fork. */
|
/* Fork. */
|
||||||
Pid pid = startProcess([&]() {
|
Pid pid = startProcess([&]() {
|
||||||
if (dup2(out.writeSide, STDOUT_FILENO) == -1)
|
if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
|
||||||
throw SysError("dupping stdout");
|
throw SysError("dupping stdout");
|
||||||
if (!input.empty()) {
|
if (!input.empty()) {
|
||||||
if (dup2(in.readSide, STDIN_FILENO) == -1)
|
if (dup2(in.readSide.get(), STDIN_FILENO) == -1)
|
||||||
throw SysError("dupping stdin");
|
throw SysError("dupping stdin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -917,16 +904,16 @@ string runProgram(Path program, bool searchPath, const Strings & args,
|
||||||
throw SysError(format("executing ‘%1%’") % program);
|
throw SysError(format("executing ‘%1%’") % program);
|
||||||
});
|
});
|
||||||
|
|
||||||
out.writeSide.close();
|
out.writeSide = -1;
|
||||||
|
|
||||||
/* FIXME: This can deadlock if the input is too long. */
|
/* FIXME: This can deadlock if the input is too long. */
|
||||||
if (!input.empty()) {
|
if (!input.empty()) {
|
||||||
in.readSide.close();
|
in.readSide = -1;
|
||||||
writeFull(in.writeSide, input);
|
writeFull(in.writeSide.get(), input);
|
||||||
in.writeSide.close();
|
in.writeSide = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
string result = drainFD(out.readSide);
|
string result = drainFD(out.readSide.get());
|
||||||
|
|
||||||
/* Wait for the child to finish. */
|
/* Wait for the child to finish. */
|
||||||
int status = pid.wait(true);
|
int status = pid.wait(true);
|
||||||
|
|
|
@ -164,16 +164,18 @@ public:
|
||||||
class AutoCloseFD
|
class AutoCloseFD
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
void close();
|
||||||
public:
|
public:
|
||||||
AutoCloseFD();
|
AutoCloseFD();
|
||||||
AutoCloseFD(int fd);
|
AutoCloseFD(int fd);
|
||||||
AutoCloseFD(const AutoCloseFD & fd);
|
AutoCloseFD(const AutoCloseFD & fd) = delete;
|
||||||
|
AutoCloseFD(AutoCloseFD&& fd);
|
||||||
~AutoCloseFD();
|
~AutoCloseFD();
|
||||||
void operator =(int fd);
|
AutoCloseFD& operator =(const AutoCloseFD & fd) = delete;
|
||||||
operator int() const;
|
AutoCloseFD& operator =(AutoCloseFD&& fd);
|
||||||
void close();
|
int get() const;
|
||||||
bool isOpen();
|
explicit operator bool() const;
|
||||||
int borrow();
|
int release();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -767,7 +767,7 @@ static void daemonLoop(char * * argv)
|
||||||
|
|
||||||
/* Create and bind to a Unix domain socket. */
|
/* Create and bind to a Unix domain socket. */
|
||||||
fdSocket = socket(PF_UNIX, SOCK_STREAM, 0);
|
fdSocket = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||||
if (fdSocket == -1)
|
if (!fdSocket)
|
||||||
throw SysError("cannot create Unix domain socket");
|
throw SysError("cannot create Unix domain socket");
|
||||||
|
|
||||||
string socketPath = settings.nixDaemonSocketFile;
|
string socketPath = settings.nixDaemonSocketFile;
|
||||||
|
@ -793,7 +793,7 @@ static void daemonLoop(char * * argv)
|
||||||
(everybody can connect --- provided they have access to the
|
(everybody can connect --- provided they have access to the
|
||||||
directory containing the socket). */
|
directory containing the socket). */
|
||||||
mode_t oldMode = umask(0111);
|
mode_t oldMode = umask(0111);
|
||||||
int res = bind(fdSocket, (struct sockaddr *) &addr, sizeof(addr));
|
int res = bind(fdSocket.get(), (struct sockaddr *) &addr, sizeof(addr));
|
||||||
umask(oldMode);
|
umask(oldMode);
|
||||||
if (res == -1)
|
if (res == -1)
|
||||||
throw SysError(format("cannot bind to socket ‘%1%’") % socketPath);
|
throw SysError(format("cannot bind to socket ‘%1%’") % socketPath);
|
||||||
|
@ -801,11 +801,11 @@ static void daemonLoop(char * * argv)
|
||||||
if (chdir("/") == -1) /* back to the root */
|
if (chdir("/") == -1) /* back to the root */
|
||||||
throw SysError("cannot change current directory");
|
throw SysError("cannot change current directory");
|
||||||
|
|
||||||
if (listen(fdSocket, 5) == -1)
|
if (listen(fdSocket.get(), 5) == -1)
|
||||||
throw SysError(format("cannot listen on socket ‘%1%’") % socketPath);
|
throw SysError(format("cannot listen on socket ‘%1%’") % socketPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
closeOnExec(fdSocket);
|
closeOnExec(fdSocket.get());
|
||||||
|
|
||||||
/* Loop accepting connections. */
|
/* Loop accepting connections. */
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -815,18 +815,18 @@ static void daemonLoop(char * * argv)
|
||||||
struct sockaddr_un remoteAddr;
|
struct sockaddr_un remoteAddr;
|
||||||
socklen_t remoteAddrLen = sizeof(remoteAddr);
|
socklen_t remoteAddrLen = sizeof(remoteAddr);
|
||||||
|
|
||||||
AutoCloseFD remote = accept(fdSocket,
|
AutoCloseFD remote = accept(fdSocket.get(),
|
||||||
(struct sockaddr *) &remoteAddr, &remoteAddrLen);
|
(struct sockaddr *) &remoteAddr, &remoteAddrLen);
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
if (remote == -1) {
|
if (!remote) {
|
||||||
if (errno == EINTR) continue;
|
if (errno == EINTR) continue;
|
||||||
throw SysError("accepting connection");
|
throw SysError("accepting connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
closeOnExec(remote);
|
closeOnExec(remote.get());
|
||||||
|
|
||||||
bool trusted = false;
|
bool trusted = false;
|
||||||
PeerInfo peer = getPeerInfo(remote);
|
PeerInfo peer = getPeerInfo(remote.get());
|
||||||
|
|
||||||
struct passwd * pw = peer.uidKnown ? getpwuid(peer.uid) : 0;
|
struct passwd * pw = peer.uidKnown ? getpwuid(peer.uid) : 0;
|
||||||
string user = pw ? pw->pw_name : std::to_string(peer.uid);
|
string user = pw ? pw->pw_name : std::to_string(peer.uid);
|
||||||
|
@ -854,7 +854,7 @@ static void daemonLoop(char * * argv)
|
||||||
options.runExitHandlers = true;
|
options.runExitHandlers = true;
|
||||||
options.allowVfork = false;
|
options.allowVfork = false;
|
||||||
startProcess([&]() {
|
startProcess([&]() {
|
||||||
fdSocket.close();
|
fdSocket = -1;
|
||||||
|
|
||||||
/* Background the daemon. */
|
/* Background the daemon. */
|
||||||
if (setsid() == -1)
|
if (setsid() == -1)
|
||||||
|
@ -870,8 +870,8 @@ static void daemonLoop(char * * argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle the connection. */
|
/* Handle the connection. */
|
||||||
from.fd = remote;
|
from.fd = remote.get();
|
||||||
to.fd = remote;
|
to.fd = remote.get();
|
||||||
processConnection(trusted);
|
processConnection(trusted);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
Loading…
Reference in a new issue