aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstore/build/local-derivation-goal.cc6
-rw-r--r--src/libutil/filesystem.cc6
-rw-r--r--src/libutil/util.hh7
3 files changed, 19 insertions, 0 deletions
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index 1fc966951..8e5ab7594 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -2528,6 +2528,12 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
[&](const DerivationOutput::CAFixed & dof) {
auto & wanted = dof.ca.hash;
+ // Replace the output by a fresh copy of itself to make sure
+ // that there's no stale file descriptor pointing to it
+ Path tmpOutput = actualPath + ".tmp";
+ movePath(actualPath, tmpOutput);
+ copyFile(tmpOutput, actualPath, true);
+
auto newInfo0 = newInfoFromCA(DerivationOutput::CAFloating {
.method = dof.ca.method,
.hashType = wanted.type,
diff --git a/src/libutil/filesystem.cc b/src/libutil/filesystem.cc
index 11cc0c0e7..2a7787c0e 100644
--- a/src/libutil/filesystem.cc
+++ b/src/libutil/filesystem.cc
@@ -133,6 +133,12 @@ void copy(const fs::directory_entry & from, const fs::path & to, bool andDelete)
}
}
+
+void copyFile(const Path & oldPath, const Path & newPath, bool andDelete)
+{
+ return copy(fs::directory_entry(fs::path(oldPath)), fs::path(newPath), andDelete);
+}
+
void renameFile(const Path & oldName, const Path & newName)
{
fs::rename(oldName, newName);
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index bcee42327..acd77ee33 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -275,6 +275,13 @@ void renameFile(const Path & src, const Path & dst);
*/
void moveFile(const Path & src, const Path & dst);
+/**
+ * Recursively copy the content of `oldPath` to `newPath`. If `andDelete` is
+ * `true`, then also remove `oldPath` (making this equivalent to `moveFile`, but
+ * with the guaranty that the destination will be “fresh”, with no stale inode
+ * or file descriptor pointing to it).
+ */
+void copyFile(const Path & oldPath, const Path & newPath, bool andDelete);
/**
* Wrappers arount read()/write() that read/write exactly the