* When using the build hook, distinguish between the stderr of the

hook script proper, and the stdout/stderr of the builder.  Only the
  latter should be saved in /nix/var/log/nix/drvs.
* Allow the verbosity to be set through an option.
* Added a flag --quiet to lower the verbosity level.
This commit is contained in:
Eelco Dolstra 2010-08-30 14:53:03 +00:00
parent 20acd43c25
commit 80e722278c
8 changed files with 47 additions and 29 deletions

View file

@ -225,14 +225,14 @@ system("NIX_SSHOPTS=\"@sshOpts\" @bindir@/nix-copy-closure $hostName $maybeSign
# Perform the build. # Perform the build.
my $buildFlags = "--max-silent-time $maxSilentTime --fallback --add-root $rootsDir/\$PPID.out"; my $buildFlags = "--max-silent-time $maxSilentTime --fallback --add-root $rootsDir/\$PPID.out --option verbosity 0";
# `-tt' forces allocation of a pseudo-terminal. This is required to # `-tt' forces allocation of a pseudo-terminal. This is required to
# make the remote nix-store process receive a signal when the # make the remote nix-store process receive a signal when the
# connection dies. Without it, the remote process might continue to # connection dies. Without it, the remote process might continue to
# run indefinitely (that is, until it next tries to write to # run indefinitely (that is, until it next tries to write to
# stdout/stderr). # stdout/stderr).
if (system("ssh $hostName @sshOpts -tt 'nix-store -r $drvPath $buildFlags > /dev/null'") != 0) { if (system("ssh $hostName @sshOpts -tt 'nix-store -r $drvPath $buildFlags > /dev/null' >&4") != 0) {
# If we couldn't run ssh or there was an ssh problem (indicated by # If we couldn't run ssh or there was an ssh problem (indicated by
# exit code 255), then we return exit code 1; otherwise we assume # exit code 255), then we return exit code 1; otherwise we assume
# that the builder failed, which we indicate to Nix using exit # that the builder failed, which we indicate to Nix using exit

View file

@ -123,6 +123,11 @@ EOF
$verbose = 1; $verbose = 1;
} }
elsif ($arg eq "--quiet") {
push @buildArgs, $arg;
push @instArgs, $arg;
}
elsif (substr($arg, 0, 1) eq "-") { elsif (substr($arg, 0, 1) eq "-") {
push @buildArgs, $arg; push @buildArgs, $arg;
} }
@ -165,7 +170,7 @@ foreach my $expr (@exprs) {
# Build. # Build.
my @outPaths; my @outPaths;
$pid = open(OUTPATHS, "-|") || exec "$binDir/nix-store", "--add-root", $outLink, "--indirect", "-rv", $pid = open(OUTPATHS, "-|") || exec "$binDir/nix-store", "--add-root", $outLink, "--indirect", "-r",
@buildArgs, @drvPaths; @buildArgs, @drvPaths;
while (<OUTPATHS>) {chomp; push @outPaths, $_;} while (<OUTPATHS>) {chomp; push @outPaths, $_;}
if (!close OUTPATHS) { if (!close OUTPATHS) {

View file

@ -196,17 +196,16 @@ static void initAndRun(int argc, char * * argv)
remaining.clear(); remaining.clear();
/* Process default options. */ /* Process default options. */
int verbosityDelta = 0;
for (Strings::iterator i = args.begin(); i != args.end(); ++i) { for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
string arg = *i; string arg = *i;
if (arg == "--verbose" || arg == "-v") if (arg == "--verbose" || arg == "-v") verbosityDelta++;
verbosity = (Verbosity) ((int) verbosity + 1); else if (arg == "--quiet") verbosityDelta--;
else if (arg == "--log-type") { else if (arg == "--log-type") {
++i; ++i;
if (i == args.end()) throw UsageError("`--log-type' requires an argument"); if (i == args.end()) throw UsageError("`--log-type' requires an argument");
setLogType(*i); setLogType(*i);
} }
else if (arg == "--build-output" || arg == "-B")
; /* !!! obsolete - remove eventually */
else if (arg == "--no-build-output" || arg == "-Q") else if (arg == "--no-build-output" || arg == "-Q")
buildVerbosity = lvlVomit; buildVerbosity = lvlVomit;
else if (arg == "--print-build-trace") else if (arg == "--print-build-trace")
@ -247,6 +246,9 @@ static void initAndRun(int argc, char * * argv)
else remaining.push_back(arg); else remaining.push_back(arg);
} }
verbosityDelta += queryIntSetting("verbosity", lvlInfo);
verbosity = (Verbosity) (verbosityDelta < 0 ? 0 : verbosityDelta);
/* Automatically clean up the temporary roots file when we /* Automatically clean up the temporary roots file when we
exit. */ exit. */
RemoveTempRoots removeTempRoots __attribute__((unused)); RemoveTempRoots removeTempRoots __attribute__((unused));

View file

@ -626,6 +626,9 @@ struct HookInstance
/* Pipe for the hook's standard output/error. */ /* Pipe for the hook's standard output/error. */
Pipe fromHook; Pipe fromHook;
/* Pipe for the builder's standard output/error. */
Pipe builderOut;
/* The process ID of the hook. */ /* The process ID of the hook. */
Pid pid; Pid pid;
@ -647,6 +650,9 @@ HookInstance::HookInstance()
/* Create the communication pipes. */ /* Create the communication pipes. */
toHook.create(); toHook.create();
/* Create a pipe to get the output of the builder. */
builderOut.create();
/* Fork the hook. */ /* Fork the hook. */
pid = fork(); pid = fork();
switch (pid) { switch (pid) {
@ -666,6 +672,11 @@ HookInstance::HookInstance()
if (dup2(toHook.readSide, STDIN_FILENO) == -1) if (dup2(toHook.readSide, 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. */
builderOut.readSide.close();
if (dup2(builderOut.writeSide, 4) == -1)
throw SysError("dupping builder's stdout/stderr");
execl(buildHook.c_str(), buildHook.c_str(), thisSystem.c_str(), execl(buildHook.c_str(), buildHook.c_str(), thisSystem.c_str(),
(format("%1%") % maxSilentTime).str().c_str(), NULL); (format("%1%") % maxSilentTime).str().c_str(), NULL);
@ -740,7 +751,7 @@ private:
AutoCloseFD fdLogFile; AutoCloseFD fdLogFile;
/* Pipe for the builder's standard output/error. */ /* Pipe for the builder's standard output/error. */
Pipe logPipe; Pipe builderOut;
/* The build hook. */ /* The build hook. */
boost::shared_ptr<HookInstance> hook; boost::shared_ptr<HookInstance> hook;
@ -1208,7 +1219,11 @@ void DerivationGoal::buildDone()
worker.childTerminated(savedPid); worker.childTerminated(savedPid);
/* Close the read side of the logger pipe. */ /* Close the read side of the logger pipe. */
logPipe.readSide.close(); if (hook) {
hook->builderOut.readSide.close();
hook->fromHook.readSide.close();
}
else builderOut.readSide.close();
/* Close the log file. */ /* Close the log file. */
fdLogFile.close(); fdLogFile.close();
@ -1388,8 +1403,10 @@ HookReply DerivationGoal::tryBuildHook()
/* Create the log file and pipe. */ /* Create the log file and pipe. */
Path logFile = openLogFile(); Path logFile = openLogFile();
worker.childStarted(shared_from_this(), set<int> fds;
hook->pid, singleton<set<int> >(hook->fromHook.readSide), false, false); fds.insert(hook->fromHook.readSide);
fds.insert(hook->builderOut.readSide);
worker.childStarted(shared_from_this(), hook->pid, fds, false, false);
if (printBuildTrace) if (printBuildTrace)
printMsg(lvlError, format("@ build-started %1% %2% %3% %4%") printMsg(lvlError, format("@ build-started %1% %2% %3% %4%")
@ -1679,8 +1696,8 @@ void DerivationGoal::startBuilder()
/* Create the log file. */ /* Create the log file. */
Path logFile = openLogFile(); Path logFile = openLogFile();
/* Create a pipe to get the output of the child. */ /* Create a pipe to get the output of the builder. */
logPipe.create(); builderOut.create();
/* Fork a child to build the package. Note that while we /* Fork a child to build the package. Note that while we
currently use forks to run and wait for the children, it currently use forks to run and wait for the children, it
@ -1732,7 +1749,7 @@ void DerivationGoal::startBuilder()
} }
#endif #endif
commonChildInit(logPipe); commonChildInit(builderOut);
if (chdir(tmpDir.c_str()) == -1) if (chdir(tmpDir.c_str()) == -1)
throw SysError(format("changing into `%1%'") % tmpDir); throw SysError(format("changing into `%1%'") % tmpDir);
@ -1816,9 +1833,9 @@ void DerivationGoal::startBuilder()
/* parent */ /* parent */
pid.setSeparatePG(true); pid.setSeparatePG(true);
logPipe.writeSide.close(); builderOut.writeSide.close();
worker.childStarted(shared_from_this(), pid, worker.childStarted(shared_from_this(), pid,
singleton<set<int> >(logPipe.readSide), true, true); singleton<set<int> >(builderOut.readSide), true, true);
if (printBuildTrace) { if (printBuildTrace) {
printMsg(lvlError, format("@ build-started %1% %2% %3% %4%") printMsg(lvlError, format("@ build-started %1% %2% %3% %4%")
@ -2008,7 +2025,8 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
{ {
if (verbosity >= buildVerbosity) if (verbosity >= buildVerbosity)
writeToStderr((unsigned char *) data.c_str(), data.size()); writeToStderr((unsigned char *) data.c_str(), data.size());
if (fdLogFile != -1) if ((hook && fd == hook->builderOut.readSide) ||
(!hook && fd == builderOut.readSide))
writeFull(fdLogFile, (unsigned char *) data.c_str(), data.size()); writeFull(fdLogFile, (unsigned char *) data.c_str(), data.size());
} }

View file

@ -20,7 +20,7 @@ string nixBinDir = "/UNINIT";
bool keepFailed = false; bool keepFailed = false;
bool keepGoing = false; bool keepGoing = false;
bool tryFallback = false; bool tryFallback = false;
Verbosity buildVerbosity = lvlInfo; Verbosity buildVerbosity = lvlError;
unsigned int maxBuildJobs = 1; unsigned int maxBuildJobs = 1;
unsigned int buildCores = 1; unsigned int buildCores = 1;
bool readOnlyMode = false; bool readOnlyMode = false;

View file

@ -97,10 +97,6 @@ void RemoteStore::forkSlave()
if (worker == "") if (worker == "")
worker = nixBinDir + "/nix-worker"; worker = nixBinDir + "/nix-worker";
string verbosityArg = "-";
for (int i = 1; i < verbosity; ++i)
verbosityArg += "v";
child = fork(); child = fork();
switch (child) { switch (child) {
@ -120,10 +116,7 @@ void RemoteStore::forkSlave()
close(fdSocket); close(fdSocket);
close(fdChild); close(fdChild);
execlp(worker.c_str(), worker.c_str(), "--slave", execlp(worker.c_str(), worker.c_str(), "--slave", NULL);
/* hacky - must be at the end */
verbosityArg == "-" ? NULL : verbosityArg.c_str(),
NULL);
throw SysError(format("executing `%1%'") % worker); throw SysError(format("executing `%1%'") % worker);

View file

@ -63,7 +63,7 @@ typedef set<Path> PathSet;
typedef enum { typedef enum {
lvlError, lvlError = 0,
lvlInfo, lvlInfo,
lvlTalkative, lvlTalkative,
lvlChatty, lvlChatty,