aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java
diff options
context:
space:
mode:
authorGravatar ulfjack <ulfjack@google.com>2018-01-19 02:55:21 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-01-19 02:56:58 -0800
commit8896d2e211c57453359566c4520615c1c1f75b66 (patch)
tree05b8d52d6a254800377f1e9d479acae5584a348a /src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java
parent76eb2a4ef5747ef881f4a3d2d1e3338e4ef8913f (diff)
Prevent broken cache entries on concurrent file changes
Local execution has an inherent race condition: if a user modifies a file while an action is executed, then it is impossible for Bazel to tell which version of the file was actually read during action execution. The file may have been modified before or after the tool has read it, or, in the worst case, the tool may have read both the original and the modified version. In addition, the file may be changed back to the original state before Bazel can check the file, so computing the digest before / after may not be sufficient. This is a concern for both local and remote caches, although the cost of poisoning a shared remote cache is significantly higher, and is what has triggered this work. Fixes #3360. We solve this by keeping a reference to the FileContentsProxy, and using that to check for modificaitons before storing the cache entry. We output a warning if this check fails. This change does not increase memory consumption; Java objects are always allocated in multiples of 8 bytes, we use compressed oops, and the FileArtifactValue currently has 12 bytes worth of fields (excl. object overhead), so adding another pointer is effectively free. As a possible performance optimization on purely local builds, we could also consider not computing digests at all, and only use the FileContentsProxy for caching. PiperOrigin-RevId: 182510358
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java')
-rw-r--r--src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java8
1 files changed, 6 insertions, 2 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java b/src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java
index dd37b3cfbd..c4c09ab068 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java
@@ -21,8 +21,11 @@ import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.ActionInputFileCache;
import com.google.devtools.build.lib.actions.cache.Metadata;
import com.google.devtools.build.lib.skyframe.FileArtifactValue;
+import com.google.devtools.build.lib.skyframe.FileContentsProxy;
+import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.Symlinks;
import com.google.devtools.remoteexecution.v1test.Digest;
import com.google.devtools.remoteexecution.v1test.Tree;
import com.google.protobuf.ByteString;
@@ -43,9 +46,10 @@ final class FakeActionInputFileCache implements ActionInputFileCache {
@Override
public Metadata getMetadata(ActionInput input) throws IOException {
String hexDigest = Preconditions.checkNotNull(cas.get(input), input);
+ Path path = execRoot.getRelative(input.getExecPath());
+ FileStatus stat = path.stat(Symlinks.FOLLOW);
return FileArtifactValue.createNormalFile(
- HashCode.fromString(hexDigest).asBytes(),
- execRoot.getRelative(input.getExecPath()).getFileSize());
+ HashCode.fromString(hexDigest).asBytes(), FileContentsProxy.create(stat), stat.getSize());
}
void setDigest(ActionInput input, String digest) {