Use vfork() instead of fork() if available
Hopefully this reduces the chance of hitting ‘unable to fork: Cannot allocate memory’ errors. vfork() is used for everything except starting builders.
This commit is contained in:
parent
48c19c4633
commit
ea89df2b76
6 changed files with 51 additions and 22 deletions
|
@ -115,6 +115,10 @@ AC_CHECK_HEADERS([sys/mount.h], [], [],
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
# Check for vfork.
|
||||||
|
AC_FUNC_FORK()
|
||||||
|
|
||||||
|
|
||||||
# Check for lutimes, optionally used for changing the mtime of
|
# Check for lutimes, optionally used for changing the mtime of
|
||||||
# symlinks.
|
# symlinks.
|
||||||
AC_CHECK_FUNCS([lutimes])
|
AC_CHECK_FUNCS([lutimes])
|
||||||
|
|
|
@ -665,7 +665,7 @@ HookInstance::HookInstance()
|
||||||
builderOut.create();
|
builderOut.create();
|
||||||
|
|
||||||
/* Fork the hook. */
|
/* Fork the hook. */
|
||||||
pid = fork();
|
pid = maybeVfork();
|
||||||
switch (pid) {
|
switch (pid) {
|
||||||
|
|
||||||
case -1:
|
case -1:
|
||||||
|
@ -2662,8 +2662,19 @@ void SubstitutionGoal::tryToRun()
|
||||||
if (pathExists(destPath))
|
if (pathExists(destPath))
|
||||||
deletePathWrapped(destPath);
|
deletePathWrapped(destPath);
|
||||||
|
|
||||||
|
worker.store.setSubstituterEnv();
|
||||||
|
|
||||||
|
/* Fill in the arguments. */
|
||||||
|
Strings args;
|
||||||
|
args.push_back(baseNameOf(sub));
|
||||||
|
args.push_back("--substitute");
|
||||||
|
args.push_back(storePath);
|
||||||
|
args.push_back(destPath);
|
||||||
|
const char * * argArr = strings2CharPtrs(args);
|
||||||
|
|
||||||
/* Fork the substitute program. */
|
/* Fork the substitute program. */
|
||||||
pid = fork();
|
pid = maybeVfork();
|
||||||
|
|
||||||
switch (pid) {
|
switch (pid) {
|
||||||
|
|
||||||
case -1:
|
case -1:
|
||||||
|
@ -2677,18 +2688,6 @@ void SubstitutionGoal::tryToRun()
|
||||||
if (dup2(outPipe.writeSide, STDOUT_FILENO) == -1)
|
if (dup2(outPipe.writeSide, STDOUT_FILENO) == -1)
|
||||||
throw SysError("cannot dup output pipe into stdout");
|
throw SysError("cannot dup output pipe into stdout");
|
||||||
|
|
||||||
/* Pass configuration options (including those overriden
|
|
||||||
with --option) to the substituter. */
|
|
||||||
setenv("_NIX_OPTIONS", settings.pack().c_str(), 1);
|
|
||||||
|
|
||||||
/* Fill in the arguments. */
|
|
||||||
Strings args;
|
|
||||||
args.push_back(baseNameOf(sub));
|
|
||||||
args.push_back("--substitute");
|
|
||||||
args.push_back(storePath);
|
|
||||||
args.push_back(destPath);
|
|
||||||
const char * * argArr = strings2CharPtrs(args);
|
|
||||||
|
|
||||||
execv(sub.c_str(), (char * *) argArr);
|
execv(sub.c_str(), (char * *) argArr);
|
||||||
|
|
||||||
throw SysError(format("executing `%1%'") % sub);
|
throw SysError(format("executing `%1%'") % sub);
|
||||||
|
|
|
@ -202,6 +202,7 @@ void checkStoreNotSymlink()
|
||||||
|
|
||||||
|
|
||||||
LocalStore::LocalStore(bool reserveSpace)
|
LocalStore::LocalStore(bool reserveSpace)
|
||||||
|
: didSetSubstituterEnv(false)
|
||||||
{
|
{
|
||||||
schemaPath = settings.nixDBPath + "/schema";
|
schemaPath = settings.nixDBPath + "/schema";
|
||||||
|
|
||||||
|
@ -943,6 +944,18 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LocalStore::setSubstituterEnv()
|
||||||
|
{
|
||||||
|
if (didSetSubstituterEnv) return;
|
||||||
|
|
||||||
|
/* Pass configuration options (including those overriden with
|
||||||
|
--option) to substituters. */
|
||||||
|
setenv("_NIX_OPTIONS", settings.pack().c_str(), 1);
|
||||||
|
|
||||||
|
didSetSubstituterEnv = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter & run)
|
void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter & run)
|
||||||
{
|
{
|
||||||
if (run.pid != -1) return;
|
if (run.pid != -1) return;
|
||||||
|
@ -955,7 +968,9 @@ void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter &
|
||||||
fromPipe.create();
|
fromPipe.create();
|
||||||
errorPipe.create();
|
errorPipe.create();
|
||||||
|
|
||||||
run.pid = fork();
|
setSubstituterEnv();
|
||||||
|
|
||||||
|
run.pid = maybeVfork();
|
||||||
|
|
||||||
switch (run.pid) {
|
switch (run.pid) {
|
||||||
|
|
||||||
|
@ -964,10 +979,6 @@ void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter &
|
||||||
|
|
||||||
case 0: /* child */
|
case 0: /* child */
|
||||||
try {
|
try {
|
||||||
/* Pass configuration options (including those overriden
|
|
||||||
with --option) to the substituter. */
|
|
||||||
setenv("_NIX_OPTIONS", settings.pack().c_str(), 1);
|
|
||||||
|
|
||||||
if (dup2(toPipe.readSide, STDIN_FILENO) == -1)
|
if (dup2(toPipe.readSide, STDIN_FILENO) == -1)
|
||||||
throw SysError("dupping stdin");
|
throw SysError("dupping stdin");
|
||||||
if (dup2(fromPipe.writeSide, STDOUT_FILENO) == -1)
|
if (dup2(fromPipe.writeSide, STDOUT_FILENO) == -1)
|
||||||
|
|
|
@ -208,6 +208,8 @@ public:
|
||||||
|
|
||||||
void markContentsGood(const Path & path);
|
void markContentsGood(const Path & path);
|
||||||
|
|
||||||
|
void setSubstituterEnv();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Path schemaPath;
|
Path schemaPath;
|
||||||
|
@ -238,6 +240,8 @@ private:
|
||||||
/* Cache for pathContentsGood(). */
|
/* Cache for pathContentsGood(). */
|
||||||
std::map<Path, bool> pathContentsGoodCache;
|
std::map<Path, bool> pathContentsGoodCache;
|
||||||
|
|
||||||
|
bool didSetSubstituterEnv;
|
||||||
|
|
||||||
int getSchema();
|
int getSchema();
|
||||||
|
|
||||||
void openDB(bool create);
|
void openDB(bool create);
|
||||||
|
|
|
@ -760,8 +760,8 @@ Pid::operator pid_t()
|
||||||
|
|
||||||
void Pid::kill()
|
void Pid::kill()
|
||||||
{
|
{
|
||||||
if (pid == -1) return;
|
if (pid == -1 || pid == 0) return;
|
||||||
|
|
||||||
printMsg(lvlError, format("killing process %1%") % pid);
|
printMsg(lvlError, format("killing process %1%") % pid);
|
||||||
|
|
||||||
/* Send the requested signal to the child. If it has its own
|
/* Send the requested signal to the child. If it has its own
|
||||||
|
@ -883,7 +883,8 @@ string runProgram(Path program, bool searchPath, const Strings & args)
|
||||||
|
|
||||||
/* Fork. */
|
/* Fork. */
|
||||||
Pid pid;
|
Pid pid;
|
||||||
pid = fork();
|
pid = maybeVfork();
|
||||||
|
|
||||||
switch (pid) {
|
switch (pid) {
|
||||||
|
|
||||||
case -1:
|
case -1:
|
||||||
|
@ -955,6 +956,13 @@ void setuidCleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if HAVE_VFORK
|
||||||
|
pid_t (*maybeVfork)() = vfork;
|
||||||
|
#else
|
||||||
|
pid_t (*maybeVfork)() = fork;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -266,6 +266,9 @@ void closeOnExec(int fd);
|
||||||
sanitize file handles 0, 1 and 2. */
|
sanitize file handles 0, 1 and 2. */
|
||||||
void setuidCleanup();
|
void setuidCleanup();
|
||||||
|
|
||||||
|
/* Call vfork() if available, otherwise fork(). */
|
||||||
|
extern pid_t (*maybeVfork)();
|
||||||
|
|
||||||
|
|
||||||
/* User interruption. */
|
/* User interruption. */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue