diff options
-rw-r--r-- | doc/manual/conf-file.xml | 15 | ||||
-rw-r--r-- | src/libstore/build.cc | 13 | ||||
-rw-r--r-- | src/libstore/globals.cc | 2 | ||||
-rw-r--r-- | src/libstore/globals.hh | 4 |
4 files changed, 34 insertions, 0 deletions
diff --git a/doc/manual/conf-file.xml b/doc/manual/conf-file.xml index c37a2da47413..c832108fed06 100644 --- a/doc/manual/conf-file.xml +++ b/doc/manual/conf-file.xml @@ -148,6 +148,7 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para> </varlistentry> + <varlistentry xml:id="conf-build-timeout"><term><literal>build-timeout</literal></term> <listitem> @@ -168,6 +169,20 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para> </varlistentry> + <varlistentry xml:id="conf-build-max-log-size"><term><literal>build-max-log-size</literal></term> + + <listitem> + + <para>This option defines the maximum number of bytes that a + builder can write to its stdout/stderr. If the builder exceeds + this limit, it’s killed. A value of <literal>0</literal> (the + default) means that there is no limit.</para> + + </listitem> + + </varlistentry> + + <varlistentry xml:id="conf-build-users-group"><term><literal>build-users-group</literal></term> <listitem><para>This options specifies the Unix group containing diff --git a/src/libstore/build.cc b/src/libstore/build.cc index b5d064e8c60d..25bf848ca697 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -813,6 +813,9 @@ private: BZFILE * bzLogFile; AutoCloseFD fdLogFile; + /* Number of bytes received from the builder's stdout/stderr. */ + unsigned long logSize; + /* Pipe for the builder's standard output/error. */ Pipe builderOut; @@ -2403,6 +2406,8 @@ string drvsLogDir = "drvs"; Path DerivationGoal::openLogFile() { + logSize = 0; + if (!settings.keepLog) return ""; string baseName = baseNameOf(drvPath); @@ -2478,6 +2483,14 @@ void DerivationGoal::handleChildOutput(int fd, const string & data) if ((hook && fd == hook->builderOut.readSide) || (!hook && fd == builderOut.readSide)) { + logSize += data.size(); + if (settings.maxLogSize && logSize > settings.maxLogSize) { + printMsg(lvlError, + format("%1% killed after writing more than %2% bytes of log output") + % getName() % settings.maxLogSize); + cancel(true); // not really a timeout, but close enough + return; + } if (verbosity >= settings.buildVerbosity) writeToStderr(data); if (bzLogFile) { diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index d17bd947d3da..aeb52e1a8696 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -46,6 +46,7 @@ Settings::Settings() impersonateLinux26 = false; keepLog = true; compressLog = true; + maxLogSize = 0; cacheFailure = false; pollInterval = 5; checkRootReachability = false; @@ -140,6 +141,7 @@ void Settings::update() get(impersonateLinux26, "build-impersonate-linux-26"); get(keepLog, "build-keep-log"); get(compressLog, "build-compress-log"); + get(maxLogSize, "build-max-log-size"); get(cacheFailure, "build-cache-failure"); get(pollInterval, "build-poll-interval"); get(checkRootReachability, "gc-check-reachability"); diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index f129d9a11edc..50b61725c742 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -153,6 +153,10 @@ struct Settings { /* Whether to compress logs. */ bool compressLog; + /* Maximum number of bytes a builder can write to stdout/stderr + before being killed (0 means no limit). */ + unsigned long maxLogSize; + /* Whether to cache build failures. */ bool cacheFailure; |