Modernize AutoCloseFD

This commit is contained in:
Shea Levy 2016-07-11 15:44:44 -04:00
parent 8a41792d43
commit cb5e7254b6
11 changed files with 139 additions and 153 deletions

View file

@ -403,7 +403,7 @@ static void commonChildInit(Pipe & logPipe)
throw SysError(format("creating a new session"));
/* 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");
/* Dup stderr to stdout. */
@ -510,11 +510,11 @@ void UserLock::acquire()
continue;
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);
if (lockFile(fd, ltWrite, false)) {
fdUserLock = fd.borrow();
if (lockFile(fd.get(), ltWrite, false)) {
fdUserLock = std::move(fd);
lockedPaths.insert(fnUserLock);
user = i;
uid = pw->pw_uid;
@ -550,7 +550,7 @@ void UserLock::acquire()
void UserLock::release()
{
if (uid == 0) return;
fdUserLock.close(); /* releases lock */
fdUserLock = -1; /* releases lock */
assert(lockedPaths.find(fnUserLock) != lockedPaths.end());
lockedPaths.erase(fnUserLock);
fnUserLock = "";
@ -613,11 +613,11 @@ HookInstance::HookInstance()
if (chdir("/") == -1) throw SysError("changing into /");
/* 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");
/* 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");
Strings args = {
@ -633,15 +633,15 @@ HookInstance::HookInstance()
});
pid.setSeparatePG(true);
fromHook.writeSide.close();
toHook.readSide.close();
fromHook.writeSide = -1;
toHook.readSide = -1;
}
HookInstance::~HookInstance()
{
try {
toHook.writeSide.close();
toHook.writeSide = -1;
pid.kill(true);
} catch (...) {
ignoreException();
@ -1414,10 +1414,10 @@ void DerivationGoal::buildDone()
/* Close the read side of the logger pipe. */
if (hook) {
hook->builderOut.readSide.close();
hook->fromHook.readSide.close();
hook->builderOut.readSide = -1;
hook->fromHook.readSide = -1;
}
else builderOut.readSide.close();
else builderOut.readSide = -1;
/* Close the log file. */
closeLogFile();
@ -1557,7 +1557,7 @@ HookReply DerivationGoal::tryBuildHook()
for (auto & i : features) checkStoreName(i); /* !!! abuse */
/* 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")
% drv->platform % drvPath % concatStringsSep(",", features)).str());
@ -1565,7 +1565,7 @@ HookReply DerivationGoal::tryBuildHook()
whether the hook wishes to perform the build. */
string reply;
while (true) {
string s = readLine(worker.hook->fromHook.readSide);
string s = readLine(worker.hook->fromHook.readSide.get());
if (string(s, 0, 2) == "# ") {
reply = string(s, 2);
break;
@ -1597,22 +1597,22 @@ HookReply DerivationGoal::tryBuildHook()
string 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
from the remote system. */
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. */
Path logFile = openLogFile();
set<int> fds;
fds.insert(hook->fromHook.readSide);
fds.insert(hook->builderOut.readSide);
fds.insert(hook->fromHook.readSide.get());
fds.insert(hook->builderOut.readSide.get());
worker.childStarted(shared_from_this(), fds, false, false);
return rpAccept;
@ -2142,17 +2142,17 @@ void DerivationGoal::startBuilder()
child = clone(childEntry, stack + stackSize, flags & ~CLONE_NEWPID, this);
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);
}, options);
if (helper.wait(true) != 0)
throw Error("unable to start build process");
userNamespaceSync.readSide.close();
userNamespaceSync.readSide = -1;
pid_t tmp;
if (!string2Int<pid_t>(readLine(builderOut.readSide), tmp)) abort();
if (!string2Int<pid_t>(readLine(builderOut.readSide.get()), tmp)) abort();
pid = tmp;
/* 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
namespace. */
writeFull(userNamespaceSync.writeSide, "1");
userNamespaceSync.writeSide.close();
writeFull(userNamespaceSync.writeSide.get(), "1");
userNamespaceSync.writeSide = -1;
} else
#endif
@ -2186,12 +2186,12 @@ void DerivationGoal::startBuilder()
/* parent */
pid.setSeparatePG(true);
builderOut.writeSide.close();
worker.childStarted(shared_from_this(), {builderOut.readSide}, true, true);
builderOut.writeSide = -1;
worker.childStarted(shared_from_this(), {builderOut.readSide.get()}, true, true);
/* Check if setting up the build environment failed. */
while (true) {
string msg = readLine(builderOut.readSide);
string msg = readLine(builderOut.readSide.get());
if (string(msg, 0, 1) == "\1") {
if (msg.size() == 1) break;
throw Error(string(msg, 1));
@ -2215,26 +2215,24 @@ void DerivationGoal::runChild()
#if __linux__
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");
userNamespaceSync.readSide.close();
userNamespaceSync.readSide = -1;
if (privateNetwork) {
/* Initialise the loopback interface. */
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;
strcpy(ifr.ifr_name, "lo");
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");
fd.close();
}
/* Set the hostname etc. to fixed values. */
@ -2919,9 +2917,9 @@ Path DerivationGoal::openLogFile()
% (settings.compressLog ? ".bz2" : "")).str();
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)
logSink = std::shared_ptr<CompressionSink>(makeCompressionSink("bzip2", *logFileSink));
@ -2938,7 +2936,7 @@ void DerivationGoal::closeLogFile()
if (logSink2) logSink2->finish();
if (logFileSink) logFileSink->flush();
logSink = logFileSink = 0;
fdLogFile.close();
fdLogFile = -1;
}
@ -2960,8 +2958,8 @@ void DerivationGoal::deleteTmpDir(bool force)
void DerivationGoal::handleChildOutput(int fd, const string & data)
{
if ((hook && fd == hook->builderOut.readSide) ||
(!hook && fd == builderOut.readSide))
if ((hook && fd == hook->builderOut.readSide.get()) ||
(!hook && fd == builderOut.readSide.get()))
{
logSize += data.size();
if (settings.maxLogSize && logSize > settings.maxLogSize) {
@ -2987,7 +2985,7 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
if (logSink) (*logSink)(data);
}
if (hook && fd == hook->fromHook.readSide)
if (hook && fd == hook->fromHook.readSide.get())
printMsg(lvlError, data); // FIXME?
}
@ -3274,7 +3272,7 @@ void SubstitutionGoal::tryToRun()
thr = std::thread([this]() {
try {
/* 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()),
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;
}
@ -3325,7 +3323,7 @@ void SubstitutionGoal::handleChildOutput(int fd, const string & data)
void SubstitutionGoal::handleEOF(int fd)
{
if (fd == outPipe.readSide) worker.wakeUp(shared_from_this());
if (fd == outPipe.readSide.get()) worker.wakeUp(shared_from_this());
}

View file

@ -34,19 +34,19 @@ int LocalStore::openGCLock(LockType lockType)
debug(format("acquiring global GC lock %1%") % fnGCLock);
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);
if (!lockFile(fdGCLock, lockType, false)) {
if (!lockFile(fdGCLock.get(), lockType, false)) {
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
process that can open the file for reading can DoS the
collector. */
return fdGCLock.borrow();
return fdGCLock.release();
}
@ -149,7 +149,7 @@ void LocalStore::addTempRoot(const Path & path)
auto state(_state.lock());
/* Create the temporary roots file for this process. */
if (state->fdTempRoots == -1) {
if (!state->fdTempRoots) {
while (1) {
Path dir = (format("%1%/%2%") % stateDir % tempRootsDir).str();
@ -166,15 +166,15 @@ void LocalStore::addTempRoot(const Path & path)
state->fdTempRoots = openLockFile(state->fnTempRoots, true);
fdGCLock.close();
fdGCLock = -1;
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
way. */
struct stat st;
if (fstat(state->fdTempRoots, &st) == -1)
if (fstat(state->fdTempRoots.get(), &st) == -1)
throw SysError(format("statting %1%") % state->fnTempRoots);
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
if the garbage collector is holding our lock. */
debug(format("acquiring write lock on %1%") % state->fnTempRoots);
lockFile(state->fdTempRoots, ltWrite, true);
lockFile(state->fdTempRoots.get(), ltWrite, true);
string s = path + '\0';
writeFull(state->fdTempRoots, s);
writeFull(state->fdTempRoots.get(), s);
/* Downgrade to a read lock. */
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);
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. */
if (errno == ENOENT) continue;
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
only succeed if the owning process has died. In that case
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);
unlink(path.c_str());
writeFull(*fd, "d");
writeFull(fd->get(), "d");
continue;
}
@ -235,10 +235,10 @@ void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds)
from upgrading to a write lock, therefore it will block in
addTempRoot(). */
debug(format("waiting for read lock on %1%") % path);
lockFile(*fd, ltRead, true);
lockFile(fd->get(), ltRead, true);
/* Read the entire file. */
string contents = readFile(*fd);
string contents = readFile(fd->get());
/* Extract the roots. */
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. */
fdGCLock.close();
fdGCLock = -1;
fds.clear();
/* Delete the trash directory. */

View file

@ -120,11 +120,11 @@ LocalStore::LocalStore(const Params & params)
AutoCloseFD fd = open(reservedPath.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, 0600);
int res = -1;
#if HAVE_POSIX_FALLOCATE
res = posix_fallocate(fd, 0, settings.reservedSize);
res = posix_fallocate(fd.get(), 0, settings.reservedSize);
#endif
if (res == -1) {
writeFull(fd, string(settings.reservedSize, 'X'));
ftruncate(fd, settings.reservedSize);
writeFull(fd.get(), string(settings.reservedSize, 'X'));
ftruncate(fd.get(), settings.reservedSize);
}
}
} catch (SysError & e) { /* don't care about errors */
@ -135,9 +135,9 @@ LocalStore::LocalStore(const Params & params)
Path globalLockPath = dbDir + "/big-lock";
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...");
lockFile(globalLock, ltRead, true);
lockFile(globalLock.get(), ltRead, true);
}
/* 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"
"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...");
lockFile(globalLock, ltWrite, true);
lockFile(globalLock.get(), ltWrite, true);
}
/* Get the schema version again, because another process may
@ -197,7 +197,7 @@ LocalStore::LocalStore(const Params & params)
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
lockFile(globalLock, ltRead, true);
lockFile(globalLock.get(), ltRead, true);
}
else openDB(*state, false);
@ -236,8 +236,8 @@ LocalStore::~LocalStore()
auto state(_state.lock());
try {
if (state->fdTempRoots != -1) {
state->fdTempRoots.close();
if (state->fdTempRoots) {
state->fdTempRoots = -1;
unlink(state->fnTempRoots.c_str());
}
} catch (...) {
@ -1115,7 +1115,7 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
/* Release the GC lock so that checking content hashes (which can
take ages) doesn't block the GC or builds. */
fdGCLock.close();
fdGCLock = -1;
/* Optionally, check the content hashes (slow). */
if (checkContents) {

View file

@ -17,10 +17,10 @@ int openLockFile(const Path & path, bool create)
AutoCloseFD fd;
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);
return fd.borrow();
return fd.release();
}
@ -119,10 +119,10 @@ bool PathLocks::lockPaths(const PathSet & _paths,
fd = openLockFile(lockPath, true);
/* Acquire an exclusive lock. */
if (!lockFile(fd, ltWrite, false)) {
if (!lockFile(fd.get(), ltWrite, false)) {
if (wait) {
if (waitMsg != "") printMsg(lvlError, waitMsg);
lockFile(fd, ltWrite, true);
lockFile(fd.get(), ltWrite, true);
} else {
/* Failed to lock this path; release all other
locks. */
@ -136,7 +136,7 @@ bool PathLocks::lockPaths(const PathSet & _paths,
/* Check that the lock file hasn't become stale (i.e.,
hasn't been unlinked). */
struct stat st;
if (fstat(fd, &st) == -1)
if (fstat(fd.get(), &st) == -1)
throw SysError(format("statting lock file %1%") % lockPath);
if (st.st_size != 0)
/* 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. */
fds.push_back(FDPair(fd.borrow(), lockPath));
fds.push_back(FDPair(fd.release(), lockPath));
lockedPaths.insert(lockPath);
}

View file

@ -66,9 +66,9 @@ ref<RemoteStore::Connection> RemoteStore::openConnection()
| SOCK_CLOEXEC
#endif
, 0);
if (conn->fd == -1)
if (!conn->fd)
throw SysError("cannot create Unix domain socket");
closeOnExec(conn->fd);
closeOnExec(conn->fd.get());
string socketPath = settings.nixDaemonSocketFile;
@ -78,11 +78,11 @@ ref<RemoteStore::Connection> RemoteStore::openConnection()
throw Error(format("socket path %1% is too long") % socketPath);
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);
conn->from.fd = conn->fd;
conn->to.fd = conn->fd;
conn->from.fd = conn->fd.get();
conn->to.fd = conn->fd.get();
/* Send the magic greeting, check for the reply. */
try {
@ -531,7 +531,7 @@ RemoteStore::Connection::~Connection()
{
try {
to.flush();
fd.close();
fd = -1;
} catch (...) {
ignoreException();
}