aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/eval.cc15
-rw-r--r--src/libexpr/eval.hh1
-rw-r--r--src/libexpr/tests/primops.cc2
-rw-r--r--src/libstore/build/derivation-goal.cc1
-rw-r--r--src/libstore/build/local-derivation-goal.cc31
-rw-r--r--src/libstore/build/personality.cc44
-rw-r--r--src/libstore/build/personality.hh11
-rw-r--r--src/libstore/builtins/buildenv.cc2
-rw-r--r--src/libstore/globals.hh5
-rw-r--r--src/libstore/local-store.cc2
-rw-r--r--src/libstore/nar-info-disk-cache.cc42
-rw-r--r--src/libutil/canon-path.hh2
-rw-r--r--src/nix/develop.cc10
-rw-r--r--src/nix/run.cc13
-rw-r--r--src/nix/run.hh3
15 files changed, 121 insertions, 63 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 084ccbee2..ebf14b659 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -67,22 +67,19 @@ static char * dupString(const char * s)
// When there's no need to write to the string, we can optimize away empty
// string allocations.
-// This function handles makeImmutableStringWithLen(null, 0) by returning the
-// empty string.
-static const char * makeImmutableStringWithLen(const char * s, size_t size)
+// This function handles makeImmutableString(std::string_view()) by returning
+// the empty string.
+static const char * makeImmutableString(std::string_view s)
{
+ const size_t size = s.size();
if (size == 0)
return "";
auto t = allocString(size + 1);
- memcpy(t, s, size);
- t[size] = 0;
+ memcpy(t, s.data(), size);
+ t[size] = '\0';
return t;
}
-static inline const char * makeImmutableString(std::string_view s) {
- return makeImmutableStringWithLen(s.data(), s.size());
-}
-
RootValue allocRootValue(Value * v)
{
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 21666339b..346b2cb31 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -60,7 +60,6 @@ void copyContext(const Value & v, PathSet & context);
typedef std::map<Path, StorePath> SrcToStore;
-std::ostream & printValue(const EvalState & state, std::ostream & str, const Value & v);
std::string printValue(const EvalState & state, const Value & v);
std::ostream & operator << (std::ostream & os, const ValueType t);
diff --git a/src/libexpr/tests/primops.cc b/src/libexpr/tests/primops.cc
index 49fbc5e98..bcdc7086b 100644
--- a/src/libexpr/tests/primops.cc
+++ b/src/libexpr/tests/primops.cc
@@ -604,7 +604,7 @@ namespace nix {
TEST_F(PrimOpTest, storeDir) {
auto v = eval("builtins.storeDir");
- ASSERT_THAT(v, IsStringEq("/nix/store"));
+ ASSERT_THAT(v, IsStringEq(settings.nixStore));
}
TEST_F(PrimOpTest, nixVersion) {
diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc
index d3b995a4f..173058d1b 100644
--- a/src/libstore/build/derivation-goal.cc
+++ b/src/libstore/build/derivation-goal.cc
@@ -39,7 +39,6 @@
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/ip.h>
-#include <sys/personality.h>
#include <sys/mman.h>
#include <sched.h>
#include <sys/param.h>
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index dccd096ec..9d869d513 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -15,6 +15,7 @@
#include "callback.hh"
#include "json-utils.hh"
#include "cgroup.hh"
+#include "personality.hh"
#include <regex>
#include <queue>
@@ -24,7 +25,6 @@
#include <termios.h>
#include <unistd.h>
#include <sys/mman.h>
-#include <sys/utsname.h>
#include <sys/resource.h>
#include <sys/socket.h>
@@ -37,7 +37,6 @@
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/ip.h>
-#include <sys/personality.h>
#include <sys/mman.h>
#include <sched.h>
#include <sys/param.h>
@@ -1964,33 +1963,7 @@ void LocalDerivationGoal::runChild()
/* Close all other file descriptors. */
closeMostFDs({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO});
-#if __linux__
- /* Change the personality to 32-bit if we're doing an
- i686-linux build on an x86_64-linux machine. */
- struct utsname utsbuf;
- uname(&utsbuf);
- if ((drv->platform == "i686-linux"
- && (settings.thisSystem == "x86_64-linux"
- || (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64"))))
- || drv->platform == "armv7l-linux"
- || drv->platform == "armv6l-linux")
- {
- if (personality(PER_LINUX32) == -1)
- throw SysError("cannot set 32-bit personality");
- }
-
- /* Impersonate a Linux 2.6 machine to get some determinism in
- builds that depend on the kernel version. */
- if ((drv->platform == "i686-linux" || drv->platform == "x86_64-linux") && settings.impersonateLinux26) {
- int cur = personality(0xffffffff);
- if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */);
- }
-
- /* Disable address space randomization for improved
- determinism. */
- int cur = personality(0xffffffff);
- if (cur != -1) personality(cur | ADDR_NO_RANDOMIZE);
-#endif
+ setPersonality(drv->platform);
/* Disable core dumps by default. */
struct rlimit limit = { 0, RLIM_INFINITY };
diff --git a/src/libstore/build/personality.cc b/src/libstore/build/personality.cc
new file mode 100644
index 000000000..4ad477869
--- /dev/null
+++ b/src/libstore/build/personality.cc
@@ -0,0 +1,44 @@
+#include "personality.hh"
+#include "globals.hh"
+
+#if __linux__
+#include <sys/utsname.h>
+#include <sys/personality.h>
+#endif
+
+#include <cstring>
+
+namespace nix {
+
+void setPersonality(std::string_view system)
+{
+#if __linux__
+ /* Change the personality to 32-bit if we're doing an
+ i686-linux build on an x86_64-linux machine. */
+ struct utsname utsbuf;
+ uname(&utsbuf);
+ if ((system == "i686-linux"
+ && (std::string_view(SYSTEM) == "x86_64-linux"
+ || (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64"))))
+ || system == "armv7l-linux"
+ || system == "armv6l-linux")
+ {
+ if (personality(PER_LINUX32) == -1)
+ throw SysError("cannot set 32-bit personality");
+ }
+
+ /* Impersonate a Linux 2.6 machine to get some determinism in
+ builds that depend on the kernel version. */
+ if ((system == "i686-linux" || system == "x86_64-linux") && settings.impersonateLinux26) {
+ int cur = personality(0xffffffff);
+ if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */);
+ }
+
+ /* Disable address space randomization for improved
+ determinism. */
+ int cur = personality(0xffffffff);
+ if (cur != -1) personality(cur | ADDR_NO_RANDOMIZE);
+#endif
+}
+
+}
diff --git a/src/libstore/build/personality.hh b/src/libstore/build/personality.hh
new file mode 100644
index 000000000..30e4f4062
--- /dev/null
+++ b/src/libstore/build/personality.hh
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <string>
+
+namespace nix {
+
+void setPersonality(std::string_view system);
+
+}
+
+
diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc
index 47458a388..b1fbda13d 100644
--- a/src/libstore/builtins/buildenv.cc
+++ b/src/libstore/builtins/buildenv.cc
@@ -95,7 +95,7 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
throw Error(
"files '%1%' and '%2%' have the same priority %3%; "
"use 'nix-env --set-flag priority NUMBER INSTALLED_PKGNAME' "
- "or type 'nix profile install --help' if using 'nix profile' to find out how"
+ "or type 'nix profile install --help' if using 'nix profile' to find out how "
"to change the priority of one of the conflicting packages"
" (0 being the highest priority)",
srcFile, readLink(dstFile), priority);
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 274a15dd7..f4d53757c 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -329,7 +329,7 @@ public:
Whether to execute builds inside cgroups.
This is only supported on Linux.
- Cgroups are required and enabled automatically for derivations
+ Cgroups are required and enabled automatically for derivations
that require the `uid-range` system feature.
> **Warning**
@@ -491,6 +491,9 @@ public:
for example, `/dev/nvidiactl?` specifies that `/dev/nvidiactl` will
only be mounted in the sandbox if it exists in the host filesystem.
+ If the source is in the Nix store, then its closure will be added to
+ the sandbox as well.
+
Depending on how Nix was built, the default value for this option
may be empty or provide `/bin/sh` as a bind-mount of `bash`.
)",
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index b67668e52..3bab10af9 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -91,6 +91,7 @@ void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd)
if (!lockFile(lockFd.get(), ltWrite, false)) {
printInfo("waiting for exclusive access to the Nix store for ca drvs...");
+ lockFile(lockFd.get(), ltNone, false); // We have acquired a shared lock; release it to prevent deadlocks
lockFile(lockFd.get(), ltWrite, true);
}
@@ -299,6 +300,7 @@ LocalStore::LocalStore(const Params & params)
if (!lockFile(globalLock.get(), ltWrite, false)) {
printInfo("waiting for exclusive access to the Nix store...");
+ lockFile(globalLock.get(), ltNone, false); // We have acquired a shared lock; release it to prevent deadlocks
lockFile(globalLock.get(), ltWrite, true);
}
diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc
index f4ea739b0..3e0689534 100644
--- a/src/libstore/nar-info-disk-cache.cc
+++ b/src/libstore/nar-info-disk-cache.cc
@@ -166,16 +166,37 @@ public:
return i->second;
}
+ std::optional<Cache> queryCacheRaw(State & state, const std::string & uri)
+ {
+ auto i = state.caches.find(uri);
+ if (i == state.caches.end()) {
+ auto queryCache(state.queryCache.use()(uri)(time(0) - cacheInfoTtl));
+ if (!queryCache.next())
+ return std::nullopt;
+ state.caches.emplace(uri,
+ Cache{(int) queryCache.getInt(0), queryCache.getStr(1), queryCache.getInt(2) != 0, (int) queryCache.getInt(3)});
+ }
+ return getCache(state, uri);
+ }
+
void createCache(const std::string & uri, const Path & storeDir, bool wantMassQuery, int priority) override
{
retrySQLite<void>([&]() {
auto state(_state.lock());
+ SQLiteTxn txn(state->db);
+
+ // To avoid the race, we have to check if maybe someone hasn't yet created
+ // the cache for this URI in the meantime.
+ auto cache(queryCacheRaw(*state, uri));
- // FIXME: race
+ if (cache)
+ return;
state->insertCache.use()(uri)(time(0))(storeDir)(wantMassQuery)(priority).exec();
assert(sqlite3_changes(state->db) == 1);
state->caches[uri] = Cache{(int) sqlite3_last_insert_rowid(state->db), storeDir, wantMassQuery, priority};
+
+ txn.commit();
});
}
@@ -183,21 +204,12 @@ public:
{
return retrySQLite<std::optional<CacheInfo>>([&]() -> std::optional<CacheInfo> {
auto state(_state.lock());
-
- auto i = state->caches.find(uri);
- if (i == state->caches.end()) {
- auto queryCache(state->queryCache.use()(uri)(time(0) - cacheInfoTtl));
- if (!queryCache.next())
- return std::nullopt;
- state->caches.emplace(uri,
- Cache{(int) queryCache.getInt(0), queryCache.getStr(1), queryCache.getInt(2) != 0, (int) queryCache.getInt(3)});
- }
-
- auto & cache(getCache(*state, uri));
-
+ auto cache(queryCacheRaw(*state, uri));
+ if (!cache)
+ return std::nullopt;
return CacheInfo {
- .wantMassQuery = cache.wantMassQuery,
- .priority = cache.priority
+ .wantMassQuery = cache->wantMassQuery,
+ .priority = cache->priority
};
});
}
diff --git a/src/libutil/canon-path.hh b/src/libutil/canon-path.hh
index c5e7f0596..9d5984584 100644
--- a/src/libutil/canon-path.hh
+++ b/src/libutil/canon-path.hh
@@ -110,7 +110,7 @@ public:
std::optional<std::string_view> dirOf() const
{
if (isRoot()) return std::nullopt;
- return path.substr(0, path.rfind('/'));
+ return ((std::string_view) path).substr(0, path.rfind('/'));
}
std::optional<std::string_view> baseName() const
diff --git a/src/nix/develop.cc b/src/nix/develop.cc
index 6c3a9c6c6..1d90d1dac 100644
--- a/src/nix/develop.cc
+++ b/src/nix/develop.cc
@@ -164,6 +164,14 @@ struct BuildEnvironment
{
return vars == other.vars && bashFunctions == other.bashFunctions;
}
+
+ std::string getSystem() const
+ {
+ if (auto v = get(vars, "system"))
+ return getString(*v);
+ else
+ return settings.thisSystem;
+ }
};
const static std::string getEnvSh =
@@ -570,7 +578,7 @@ struct CmdDevelop : Common, MixEnvironment
}
}
- runProgramInStore(store, shell, args);
+ runProgramInStore(store, shell, args, buildEnvironment.getSystem());
}
};
diff --git a/src/nix/run.cc b/src/nix/run.cc
index 45d2dfd0d..6fca68047 100644
--- a/src/nix/run.cc
+++ b/src/nix/run.cc
@@ -9,6 +9,7 @@
#include "fs-accessor.hh"
#include "progress-bar.hh"
#include "eval.hh"
+#include "build/personality.hh"
#if __linux__
#include <sys/mount.h>
@@ -24,7 +25,8 @@ namespace nix {
void runProgramInStore(ref<Store> store,
const std::string & program,
- const Strings & args)
+ const Strings & args,
+ std::optional<std::string_view> system)
{
stopProgressBar();
@@ -44,7 +46,7 @@ void runProgramInStore(ref<Store> store,
throw Error("store '%s' is not a local store so it does not support command execution", store->getUri());
if (store->storeDir != store2->getRealStoreDir()) {
- Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program };
+ Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), std::string(system.value_or("")), program };
for (auto & arg : args) helperArgs.push_back(arg);
execv(getSelfExe().value_or("nix").c_str(), stringsToCharPtrs(helperArgs).data());
@@ -52,6 +54,9 @@ void runProgramInStore(ref<Store> store,
throw SysError("could not execute chroot helper");
}
+ if (system)
+ setPersonality(*system);
+
execvp(program.c_str(), stringsToCharPtrs(args).data());
throw SysError("unable to execute '%s'", program);
@@ -199,6 +204,7 @@ void chrootHelper(int argc, char * * argv)
int p = 1;
std::string storeDir = argv[p++];
std::string realStoreDir = argv[p++];
+ std::string system = argv[p++];
std::string cmd = argv[p++];
Strings args;
while (p < argc)
@@ -262,6 +268,9 @@ void chrootHelper(int argc, char * * argv)
writeFile("/proc/self/uid_map", fmt("%d %d %d", uid, uid, 1));
writeFile("/proc/self/gid_map", fmt("%d %d %d", gid, gid, 1));
+ if (system != "")
+ setPersonality(system);
+
execvp(cmd.c_str(), stringsToCharPtrs(args).data());
throw SysError("unable to exec '%s'", cmd);
diff --git a/src/nix/run.hh b/src/nix/run.hh
index 6180a87dd..fed360158 100644
--- a/src/nix/run.hh
+++ b/src/nix/run.hh
@@ -6,6 +6,7 @@ namespace nix {
void runProgramInStore(ref<Store> store,
const std::string & program,
- const Strings & args);
+ const Strings & args,
+ std::optional<std::string_view> system = std::nullopt);
}