Description redacted.
--
MOS_MIGRATED_REVID=133693782
diff --git a/src/main/cpp/blaze.cc b/src/main/cpp/blaze.cc
index 493d367..65e1522 100644
--- a/src/main/cpp/blaze.cc
+++ b/src/main/cpp/blaze.cc
@@ -825,7 +825,7 @@
 static char server_output_buffer[8192];
 
 // Forwards the output of the server to the specified file handle.
-static int ForwardServerOutput(int socket, int output) {
+static int ForwardServerOutput(int socket, int output, bool* pipe_broken) {
   unsigned int remaining;
   int exit_code = ReadServerInt(socket, &remaining);
   if (exit_code != 0) {
@@ -839,7 +839,9 @@
     }
 
     remaining -= bytes;
-    (void) write(output, server_output_buffer, bytes);
+    if (write(output, server_output_buffer, bytes) < 0 && errno == EPIPE) {
+      *pipe_broken = true;
+    }
   }
 
   return 0;
@@ -900,9 +902,11 @@
   const int TAG_STDERR = 2;
   const int TAG_CONTROL = 3;
   unsigned int exit_code;
+  bool pipe_broken = false;
   for (;;) {
     // Read the tag
     unsigned char tag;
+    bool pipe_broken_now = false;
     exit_code = ReadServerChar(server_socket_, &tag);
     if (exit_code != 0) {
       return exit_code;
@@ -911,18 +915,28 @@
     switch (tag) {
       // stdout
       case TAG_STDOUT:
-        exit_code = ForwardServerOutput(server_socket_, STDOUT_FILENO);
+        exit_code = ForwardServerOutput(server_socket_, STDOUT_FILENO,
+                                        &pipe_broken_now);
         if (exit_code != 0) {
           return exit_code;
         }
+        if (pipe_broken_now && !pipe_broken) {
+          pipe_broken = true;
+          Cancel();
+        }
         break;
 
       // stderr
       case TAG_STDERR:
-        exit_code = ForwardServerOutput(server_socket_, STDERR_FILENO);
+        exit_code = ForwardServerOutput(server_socket_, STDERR_FILENO,
+                                        &pipe_broken_now);
         if (exit_code != 0) {
           return exit_code;
         }
+        if (pipe_broken_now && !pipe_broken) {
+          pipe_broken = true;
+          Cancel();
+        }
         break;
 
       // Control stream. Currently only used for reporting the exit code.
@@ -1493,9 +1507,6 @@
       blaze_server->Cancel();
       break;
     case SIGPIPE:
-      // Don't bother the user with a message in this case; they're
-      // probably using head(1) or more(1).
-      blaze_server->Cancel();
       globals->received_signal = SIGPIPE;
       break;
     case SIGQUIT:
@@ -2100,20 +2111,33 @@
 
   std::thread cancel_thread(&GrpcBlazeServer::CancelThread, this);
   bool command_id_set = false;
+  bool pipe_broken = false;
   while (reader->Read(&response)) {
     if (response.cookie() != response_cookie_) {
       fprintf(stderr, "\nServer response cookie invalid, exiting\n");
       return blaze_exit_code::INTERNAL_ERROR;
     }
 
+    bool pipe_broken_now = false;
     if (response.standard_output().size() > 0) {
-      (void) write(STDOUT_FILENO, response.standard_output().c_str(),
-                   response.standard_output().size());
+      int result = write(STDOUT_FILENO, response.standard_output().c_str(),
+                         response.standard_output().size());
+      if (result < 0 && errno == EPIPE) {
+        pipe_broken_now = true;
+      }
     }
 
     if (response.standard_error().size() > 0) {
-      (void) write(STDERR_FILENO, response.standard_error().c_str(),
-                   response.standard_error().size());
+      int result = write(STDERR_FILENO, response.standard_error().c_str(),
+                         response.standard_error().size());
+      if (result < 0 && errno == EPIPE) {
+        pipe_broken_now = true;
+      }
+    }
+
+    if (pipe_broken_now && !pipe_broken) {
+      pipe_broken = true;
+      Cancel();
     }
 
     if (!command_id_set && response.command_id().size() > 0) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/TestActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/test/TestActionBuilder.java
index f0a2733..5992a80 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/test/TestActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/test/TestActionBuilder.java
@@ -241,27 +241,35 @@
 
     for (int run = 0; run < runsPerTest; run++) {
       // Use a 1-based index for user friendliness.
-      String runSuffix =
-          runsPerTest > 1 ? String.format("_run_%d_of_%d", run + 1, runsPerTest) : "";
+      String testRunDir =
+          runsPerTest > 1 ? String.format("run_%d_of_%d", run + 1, runsPerTest) : "";
       for (int shard = 0; shard < shardRuns; shard++) {
-        String suffix = (shardRuns > 1 ? String.format("_shard_%d_of_%d", shard + 1, shards) : "")
-            + runSuffix;
-        Artifact testLog = ruleContext.getPackageRelativeArtifact(
-            targetName.getRelative("test" + suffix + ".log"), root);
-        Artifact cacheStatus = ruleContext.getPackageRelativeArtifact(
-            targetName.getRelative("test" + suffix + ".cache_status"), root);
+        String shardRunDir =
+            (shardRuns > 1 ? String.format("shard_%d_of_%d", shard + 1, shards) : "");
+        if (testRunDir.isEmpty()) {
+          shardRunDir = shardRunDir.isEmpty() ? "" : shardRunDir + PathFragment.SEPARATOR_CHAR;
+        } else {
+          testRunDir += PathFragment.SEPARATOR_CHAR;
+          shardRunDir = shardRunDir.isEmpty() ? testRunDir : shardRunDir + "_" + testRunDir;
+        }
+        Artifact testLog =
+            ruleContext.getPackageRelativeArtifact(
+                targetName.getRelative(shardRunDir + "test.log"), root);
+        Artifact cacheStatus =
+            ruleContext.getPackageRelativeArtifact(
+                targetName.getRelative(shardRunDir + "test.cache_status"), root);
 
         Artifact coverageArtifact = null;
         if (collectCodeCoverage) {
           coverageArtifact = ruleContext.getPackageRelativeArtifact(
-              targetName.getRelative("coverage" + suffix + ".dat"), root);
+              targetName.getRelative(shardRunDir + "coverage.dat"), root);
           coverageArtifacts.add(coverageArtifact);
         }
 
         Artifact microCoverageArtifact = null;
         if (collectCodeCoverage && config.isMicroCoverageEnabled()) {
           microCoverageArtifact = ruleContext.getPackageRelativeArtifact(
-              targetName.getRelative("coverage" + suffix + ".micro.dat"), root);
+              targetName.getRelative(shardRunDir + "coverage.micro.dat"), root);
         }
 
         env.registerAction(new TestRunnerAction(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/TestRunnerAction.java b/src/main/java/com/google/devtools/build/lib/rules/test/TestRunnerAction.java
index 473ec92..19bfdb3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/test/TestRunnerAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/test/TestRunnerAction.java
@@ -80,7 +80,6 @@
   private final PathFragment testStderr;
   private final PathFragment testInfrastructureFailure;
   private final PathFragment baseDir;
-  private final String namePrefix;
   private final Artifact coverageData;
   private final Artifact microCoverageData;
   private final TestTargetProperties testProperties;
@@ -143,29 +142,28 @@
     this.executionSettings = Preconditions.checkNotNull(executionSettings);
 
     this.baseDir = cacheStatus.getExecPath().getParentDirectory();
-    this.namePrefix = FileSystemUtils.removeExtension(cacheStatus.getExecPath().getBaseName());
 
     int totalShards = executionSettings.getTotalShards();
     Preconditions.checkState((totalShards == 0 && shardNum == 0) ||
                                 (totalShards > 0 && 0 <= shardNum && shardNum < totalShards));
-    this.testExitSafe = baseDir.getChild(namePrefix + ".exited_prematurely");
+    this.testExitSafe = baseDir.getChild("test.exited_prematurely");
     // testShard Path should be set only if sharding is enabled.
     this.testShard = totalShards > 1
-        ? baseDir.getChild(namePrefix + ".shard")
+        ? baseDir.getChild("test.shard")
         : null;
-    this.xmlOutputPath = baseDir.getChild(namePrefix + ".xml");
-    this.testWarningsPath = baseDir.getChild(namePrefix + ".warnings");
-    this.unusedRunfilesLogPath = baseDir.getChild(namePrefix + ".unused_runfiles_log");
-    this.testStderr = baseDir.getChild(namePrefix + ".err");
-    this.splitLogsDir = baseDir.getChild(namePrefix + ".raw_splitlogs");
+    this.xmlOutputPath = baseDir.getChild("test.xml");
+    this.testWarningsPath = baseDir.getChild("test.warnings");
+    this.unusedRunfilesLogPath = baseDir.getChild("test.unused_runfiles_log");
+    this.testStderr = baseDir.getChild("test.err");
+    this.splitLogsDir = baseDir.getChild("test.raw_splitlogs");
     // See note in {@link #getSplitLogsPath} on the choice of file name.
     this.splitLogsPath = splitLogsDir.getChild("test.splitlogs");
-    this.undeclaredOutputsDir = baseDir.getChild(namePrefix + ".outputs");
+    this.undeclaredOutputsDir = baseDir.getChild("test.outputs");
     this.undeclaredOutputsZipPath = undeclaredOutputsDir.getChild("outputs.zip");
-    this.undeclaredOutputsAnnotationsDir = baseDir.getChild(namePrefix + ".outputs_manifest");
+    this.undeclaredOutputsAnnotationsDir = baseDir.getChild("test.outputs_manifest");
     this.undeclaredOutputsManifestPath = undeclaredOutputsAnnotationsDir.getChild("MANIFEST");
     this.undeclaredOutputsAnnotationsPath = undeclaredOutputsAnnotationsDir.getChild("ANNOTATIONS");
-    this.testInfrastructureFailure = baseDir.getChild(namePrefix + ".infrastructure_failure");
+    this.testInfrastructureFailure = baseDir.getChild("test.infrastructure_failure");
     this.workspaceName = workspaceName;
 
     Map<String, String> mergedTestEnv = new HashMap<>(configuration.getTestEnv());
@@ -181,10 +179,6 @@
     return baseDir;
   }
 
-  public final String getNamePrefix() {
-    return namePrefix;
-  }
-
   @Override
   public boolean showsOutputUnconditionally() {
     return true;
@@ -336,7 +330,7 @@
     execRoot.getRelative(testInfrastructureFailure).delete();
 
     // Coverage files use "coverage" instead of "test".
-    String coveragePrefix = "coverage" + namePrefix.substring(4);
+    String coveragePrefix = "coverage";
 
     // We cannot use coverageData artifact since it may be null. Generate coverage name instead.
     execRoot.getRelative(baseDir.getChild(coveragePrefix + ".dat")).delete();
@@ -344,8 +338,8 @@
     execRoot.getRelative(baseDir.getChild(coveragePrefix + ".micro.dat")).delete();
 
     // Delete files fetched from remote execution.
-    execRoot.getRelative(baseDir.getChild(namePrefix + ".zip")).delete();
-    deleteTestAttemptsDirMaybe(execRoot.getRelative(baseDir), namePrefix);
+    execRoot.getRelative(baseDir.getChild("test.zip")).delete();
+    deleteTestAttemptsDirMaybe(execRoot.getRelative(baseDir), "test");
   }
 
   private void deleteTestAttemptsDirMaybe(Path outputDir, String namePrefix) throws IOException {
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
index 0f2f745..f2406dd 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
@@ -482,7 +482,7 @@
     config.create(
         "tools/cpp/BUILD",
         "cc_library(name = 'stl')",
-        "filegroup(name='toolchain', srcs=['//third_party/crosstool'])");
+        "alias(name='toolchain', actual='//third_party/crosstool')");
   }
 
   protected void createCrosstoolPackage(MockToolsConfig config, boolean addEmbeddedRuntimes)
diff --git a/tools/cpp/BUILD b/tools/cpp/BUILD
index f693fe7..50d19a8 100644
--- a/tools/cpp/BUILD
+++ b/tools/cpp/BUILD
@@ -23,9 +23,9 @@
 #   * all file groups that said cc_toolchain might refer to,
 # including the default_grte_top setting in the CROSSTOOL
 # protobuf.
-filegroup(
+alias(
     name = "toolchain",
-    srcs = ["//external:cc_toolchain"],
+    actual = "//external:cc_toolchain",
 )
 
 # Hardcoded toolchain, legacy behaviour.