Don't crash on I/O exceptions when creating BuildEventArtifactUploader: they can happen when underlying state is bad.

PiperOrigin-RevId: 295771133
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java
index b468ab0..b490176 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java
+++ b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java
@@ -18,8 +18,6 @@
 import com.google.common.base.Preconditions;
 import com.google.common.base.Stopwatch;
 import com.google.common.base.Strings;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -72,6 +70,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
@@ -314,8 +313,8 @@
             : "local";
 
     CountingArtifactGroupNamer artifactGroupNamer = new CountingArtifactGroupNamer();
-    Supplier<BuildEventArtifactUploader> uploaderSupplier =
-        Suppliers.memoize(
+    ThrowingBuildEventArtifactUploaderSupplier uploaderSupplier =
+        new ThrowingBuildEventArtifactUploaderSupplier(
             () ->
                 cmdEnv
                     .getRuntime()
@@ -334,7 +333,14 @@
       return;
     }
 
-    bepTransports = createBepTransports(cmdEnv, uploaderSupplier, artifactGroupNamer);
+    try {
+      bepTransports = createBepTransports(cmdEnv, uploaderSupplier, artifactGroupNamer);
+    } catch (IOException e) {
+      cmdEnv
+          .getBlazeModuleEnvironment()
+          .exit(new AbruptExitException(ExitCode.LOCAL_ENVIRONMENTAL_ERROR, e));
+      return;
+    }
     if (bepTransports.isEmpty()) {
       // Exit early if there are no transports to stream to.
       return;
@@ -601,8 +607,9 @@
   @Nullable
   private BuildEventServiceTransport createBesTransport(
       CommandEnvironment cmdEnv,
-      Supplier<BuildEventArtifactUploader> uploaderSupplier,
-      CountingArtifactGroupNamer artifactGroupNamer) {
+      ThrowingBuildEventArtifactUploaderSupplier uploaderSupplier,
+      CountingArtifactGroupNamer artifactGroupNamer)
+      throws IOException {
     if (Strings.isNullOrEmpty(besOptions.besBackend)) {
       clearBesClient();
       return null;
@@ -672,8 +679,9 @@
 
   private ImmutableSet<BuildEventTransport> createBepTransports(
       CommandEnvironment cmdEnv,
-      Supplier<BuildEventArtifactUploader> uploaderSupplier,
-      CountingArtifactGroupNamer artifactGroupNamer) {
+      ThrowingBuildEventArtifactUploaderSupplier uploaderSupplier,
+      CountingArtifactGroupNamer artifactGroupNamer)
+      throws IOException {
     ImmutableSet.Builder<BuildEventTransport> bepTransportsBuilder = new ImmutableSet.Builder<>();
 
     if (!Strings.isNullOrEmpty(besStreamOptions.buildEventTextFile)) {
@@ -805,4 +813,31 @@
   ImmutableSet<BuildEventTransport> getBepTransports() {
     return bepTransports;
   }
+
+  private static class ThrowingBuildEventArtifactUploaderSupplier {
+    private final Callable<BuildEventArtifactUploader> callable;
+    @Nullable private BuildEventArtifactUploader memoizedValue;
+    @Nullable private IOException exception;
+
+    ThrowingBuildEventArtifactUploaderSupplier(Callable<BuildEventArtifactUploader> callable) {
+      this.callable = callable;
+    }
+
+    BuildEventArtifactUploader get() throws IOException {
+      if (memoizedValue == null && exception == null) {
+        try {
+          memoizedValue = callable.call();
+        } catch (IOException e) {
+          exception = e;
+        } catch (Exception e) {
+          Throwables.throwIfUnchecked(e);
+          throw new IllegalStateException(e);
+        }
+      }
+      if (memoizedValue != null) {
+        return memoizedValue;
+      }
+      throw exception;
+    }
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
index 0f4bb97..26e54f3 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
@@ -543,7 +543,7 @@
     }
 
     @Override
-    public BuildEventArtifactUploader create(CommandEnvironment env) {
+    public BuildEventArtifactUploader create(CommandEnvironment env) throws IOException {
       BuildEventArtifactUploaderFactory uploaderFactory0 = this.uploaderFactory;
       if (uploaderFactory0 == null) {
         return new LocalFilesArtifactUploader();
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
index 09b50ad..837a6d1 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
@@ -282,7 +282,7 @@
   }
 
   private BuildEventArtifactUploader newUploader(
-      CommandEnvironment env, String buildEventUploadStrategy) {
+      CommandEnvironment env, String buildEventUploadStrategy) throws IOException {
     return getBuildEventArtifactUploaderFactoryMap().select(buildEventUploadStrategy).create(env);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BuildEventArtifactUploaderFactory.java b/src/main/java/com/google/devtools/build/lib/runtime/BuildEventArtifactUploaderFactory.java
index b48b309..d4ee8dd 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BuildEventArtifactUploaderFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BuildEventArtifactUploaderFactory.java
@@ -16,6 +16,7 @@
 
 import com.google.devtools.build.lib.buildeventstream.BuildEventArtifactUploader;
 import com.google.devtools.build.lib.buildeventstream.LocalFilesArtifactUploader;
+import java.io.IOException;
 
 /** A factory for {@link BuildEventArtifactUploader}. */
 public interface BuildEventArtifactUploaderFactory {
@@ -27,6 +28,6 @@
    * Returns a new instance of a {@link BuildEventArtifactUploader}. The call is responsible for
    * calling {@link BuildEventArtifactUploader#shutdown()} on the returned instance.
    */
-  BuildEventArtifactUploader create(CommandEnvironment env);
+  BuildEventArtifactUploader create(CommandEnvironment env) throws IOException;
 }
 
diff --git a/src/test/java/com/google/devtools/build/lib/buildeventstream/BuildEventArtifactUploaderFactoryMapTest.java b/src/test/java/com/google/devtools/build/lib/buildeventstream/BuildEventArtifactUploaderFactoryMapTest.java
index cef128b..a760ef0 100644
--- a/src/test/java/com/google/devtools/build/lib/buildeventstream/BuildEventArtifactUploaderFactoryMapTest.java
+++ b/src/test/java/com/google/devtools/build/lib/buildeventstream/BuildEventArtifactUploaderFactoryMapTest.java
@@ -22,6 +22,7 @@
 import com.google.devtools.build.lib.runtime.BuildEventArtifactUploaderFactoryMap;
 import com.google.devtools.build.lib.runtime.CommandEnvironment;
 import com.google.devtools.build.lib.vfs.Path;
+import java.io.IOException;
 import java.util.Map;
 import org.junit.Before;
 import org.junit.Test;
@@ -70,7 +71,7 @@
   }
 
   @Test
-  public void testAlphabeticalOrder() {
+  public void testAlphabeticalOrder() throws IOException {
     assertThat(uploaderFactories.select(null).create(null).getClass())
         .isEqualTo(LocalFilesArtifactUploader.class);
   }