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…
	
	Add table
		Add a link
		
	
		Reference in a new issue