Remove the dependency between the Blaze LC and the windows subprocesses.

PiperOrigin-RevId: 848148332
Change-Id: Idc5365d67e7472b47155cb8171ec82a53def68d8
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BUILD b/src/main/java/com/google/devtools/build/lib/bazel/BUILD
index 0804711..ce31fe5 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/bazel/BUILD
@@ -196,6 +196,7 @@
         "//src/main/java/com/google/devtools/build/lib/remote",
         "//src/main/java/com/google/devtools/build/lib/runtime/mobileinstall",
         "//src/main/java/com/google/devtools/build/lib/sandbox:sandbox_module",
+        "//src/main/java/com/google/devtools/build/lib/shell:windows_subprocess_factory",
         "//src/main/java/com/google/devtools/build/lib/skyframe:fs_events_native_deps_service_impl",
         "//src/main/java/com/google/devtools/build/lib/skyframe:skymeld_module",
         "//src/main/java/com/google/devtools/build/lib/skyframe/serialization:serialization_module",
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java b/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java
index 824ad46..00363ea 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java
@@ -20,6 +20,7 @@
 import com.google.devtools.build.lib.runtime.BlazeModule;
 import com.google.devtools.build.lib.runtime.BlazeRuntime;
 import com.google.devtools.build.lib.runtime.BlazeService;
+import com.google.devtools.build.lib.shell.WindowsSubprocessFactory;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Properties;
@@ -112,6 +113,10 @@
           new com.google.devtools.build.lib.unix.ProcessUtilsServiceImpl());
 
   public static void main(String[] args) {
+    // Sets the default subprocess factory to the Windows-specific implementation if the host OS is
+    // Windows. We do this in Bazel.java to make sure that the global state is set before the first
+    // use of SubprocessBuilder.
+    WindowsSubprocessFactory.maybeInstallWindowsSubprocessFactory();
     BlazeVersionInfo.setBuildInfo(tryGetBuildInfo());
     BlazeRuntime.main(BAZEL_MODULES, BAZEL_SERVICES, args);
   }
diff --git a/src/main/java/com/google/devtools/build/lib/shell/BUILD b/src/main/java/com/google/devtools/build/lib/shell/BUILD
index 6f6dd86..020e19d 100644
--- a/src/main/java/com/google/devtools/build/lib/shell/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/shell/BUILD
@@ -11,22 +11,27 @@
     visibility = ["//src:__subpackages__"],
 )
 
+WINDOWS_SRCS = [
+    "WindowsSubprocess.java",
+    "WindowsSubprocessFactory.java",
+]
+
 # Library for dealing with executable commands, including their arguments and runtime environment
 # (environment variables, working directory). It lets a caller execute a command, get its results,
 # and optionally forward interrupts to the subprocess. The library also handles creating threads to
 # ensure timely reading of subprocess outputs.
 java_library(
     name = "shell",
-    srcs = glob(["*.java"]),
+    srcs = glob(
+        ["*.java"],
+        exclude = WINDOWS_SRCS,
+    ),
     deps = [
-        "//src/main/java/com/google/devtools/build/lib/jni",
-        "//src/main/java/com/google/devtools/build/lib/util:cleaner",
+        "//src/main/java/com/google/devtools/build/lib/util:TestType",
         "//src/main/java/com/google/devtools/build/lib/util:describable_execution_unit",
         "//src/main/java/com/google/devtools/build/lib/util:os",
         "//src/main/java/com/google/devtools/build/lib/util:string_encoding",
         "//src/main/java/com/google/devtools/build/lib/vfs",
-        "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
-        "//src/main/java/com/google/devtools/build/lib/windows:processes",
         "//src/main/protobuf:execution_statistics_java_proto",
         "//third_party:auto_value",
         "//third_party:flogger",
@@ -34,3 +39,19 @@
         "//third_party:jsr305",
     ],
 )
+
+java_library(
+    name = "windows_subprocess_factory",
+    srcs = WINDOWS_SRCS,
+    deps = [
+        ":shell",
+        "//src/main/java/com/google/devtools/build/lib/jni",
+        "//src/main/java/com/google/devtools/build/lib/util:cleaner",
+        "//src/main/java/com/google/devtools/build/lib/util:os",
+        "//src/main/java/com/google/devtools/build/lib/util:string_encoding",
+        "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
+        "//src/main/java/com/google/devtools/build/lib/windows:processes",
+        "//third_party:guava",
+        "//third_party:jsr305",
+    ],
+)
diff --git a/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java b/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java
index d81235d..599f95a 100644
--- a/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java
@@ -14,8 +14,10 @@
 
 package com.google.devtools.build.lib.shell;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.devtools.build.lib.shell.SubprocessBuilder.StreamAction;
+import com.google.devtools.build.lib.util.OS;
 import com.google.devtools.build.lib.util.StringEncoding;
 import java.io.File;
 import java.io.IOException;
@@ -159,6 +161,10 @@
 
   @Override
   public Subprocess create(SubprocessBuilder params) throws IOException {
+    Preconditions.checkState(
+        OS.getCurrent() != OS.WINDOWS,
+        "attempting to use non-Windows subprocess factory on Windows - did you forget to call"
+            + " WindowsSubprocessFactory.maybeInstallWindowsSubprocessFactory?");
     ProcessBuilder builder = new ProcessBuilder();
     builder.command(Lists.transform(params.getArgv(), StringEncoding::internalToPlatform));
     builder.environment().clear();
diff --git a/src/main/java/com/google/devtools/build/lib/shell/SubprocessBuilder.java b/src/main/java/com/google/devtools/build/lib/shell/SubprocessBuilder.java
index b783802..e9574a7 100644
--- a/src/main/java/com/google/devtools/build/lib/shell/SubprocessBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/shell/SubprocessBuilder.java
@@ -14,13 +14,11 @@
 
 package com.google.devtools.build.lib.shell;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.jni.JniLoader;
-import com.google.devtools.build.lib.util.OS;
 import com.google.devtools.build.lib.util.StringEncoding;
+import com.google.devtools.build.lib.util.TestType;
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.io.File;
 import java.io.IOException;
@@ -28,6 +26,7 @@
 import javax.annotation.Nullable;
 
 /** A builder class that starts a subprocess. */
+@SuppressWarnings("NonFinalStaticField")
 public class SubprocessBuilder {
   /** What to do with an output stream of the process. */
   public enum StreamAction {
@@ -53,24 +52,18 @@
   private long timeoutMillis;
   private boolean redirectErrorStream;
 
-  static SubprocessFactory defaultFactory = subprocessFactoryImplementation();
+  // We make this field non-final to allow it to be set to the Windows-specific implementation,
+  // therefore avoiding the direct dependency on the WindowsSubprocessFactory.
+  private static SubprocessFactory defaultFactory = JavaSubprocessFactory.INSTANCE;
+  private static boolean defaultFactoryOverridden = false;
 
-  private static SubprocessFactory subprocessFactoryImplementation() {
-    if (JniLoader.isJniAvailable() && OS.getCurrent() == OS.WINDOWS) {
-      return WindowsSubprocessFactory.INSTANCE;
-    } else {
-      return JavaSubprocessFactory.INSTANCE;
-    }
-  }
-
-  /**
-   * Sets the default factory class for creating subprocesses. Passing {@code null} resets it to the
-   * initial state.
-   */
-  @VisibleForTesting
+  /** Sets the default factory class for creating subprocesses. */
   public static void setDefaultSubprocessFactory(SubprocessFactory factory) {
-    SubprocessBuilder.defaultFactory =
-        factory != null ? factory : subprocessFactoryImplementation();
+    if (defaultFactoryOverridden && !TestType.isInTest()) {
+      throw new IllegalStateException("SubprocessFactory has already been set.");
+    }
+    SubprocessBuilder.defaultFactory = factory;
+    defaultFactoryOverridden = true;
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/shell/WindowsSubprocessFactory.java b/src/main/java/com/google/devtools/build/lib/shell/WindowsSubprocessFactory.java
index 97e8d3a..1a5ee25 100644
--- a/src/main/java/com/google/devtools/build/lib/shell/WindowsSubprocessFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/shell/WindowsSubprocessFactory.java
@@ -16,10 +16,13 @@
 
 import static java.nio.charset.StandardCharsets.UTF_16LE;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
+import com.google.devtools.build.lib.jni.JniLoader;
 import com.google.devtools.build.lib.shell.SubprocessBuilder.StreamAction;
+import com.google.devtools.build.lib.util.OS;
 import com.google.devtools.build.lib.util.StringEncoding;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.lib.windows.WindowsProcesses;
@@ -35,8 +38,15 @@
 public class WindowsSubprocessFactory implements SubprocessFactory {
   public static final WindowsSubprocessFactory INSTANCE = new WindowsSubprocessFactory();
 
+  public static void maybeInstallWindowsSubprocessFactory() {
+    if (JniLoader.isJniAvailable() && OS.getCurrent() == OS.WINDOWS) {
+      SubprocessBuilder.setDefaultSubprocessFactory(INSTANCE);
+    }
+  }
+
   @Override
   public Subprocess create(SubprocessBuilder builder) throws IOException {
+    Preconditions.checkState(OS.getCurrent() == OS.WINDOWS);
     List<String> argv = Lists.transform(builder.getArgv(), StringEncoding::internalToPlatform);
 
     // DO NOT quote argv0, createProcess will do it for us.
diff --git a/src/test/java/com/google/devtools/build/lib/authandtls/credentialhelper/BUILD b/src/test/java/com/google/devtools/build/lib/authandtls/credentialhelper/BUILD
index 4b806ed..e08a8ac 100644
--- a/src/test/java/com/google/devtools/build/lib/authandtls/credentialhelper/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/authandtls/credentialhelper/BUILD
@@ -30,6 +30,7 @@
         "//src/main/java/com/google/devtools/build/lib/authandtls/credentialhelper",
         "//src/main/java/com/google/devtools/build/lib/authandtls/credentialhelper:credential_module",
         "//src/main/java/com/google/devtools/build/lib/events",
+        "//src/main/java/com/google/devtools/build/lib/shell:windows_subprocess_factory",
         "//src/main/java/com/google/devtools/build/lib/util:os",
         "//src/main/java/com/google/devtools/build/lib/vfs",
         "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
diff --git a/src/test/java/com/google/devtools/build/lib/authandtls/credentialhelper/CredentialHelperTest.java b/src/test/java/com/google/devtools/build/lib/authandtls/credentialhelper/CredentialHelperTest.java
index 67c1e0f..a824f88 100644
--- a/src/test/java/com/google/devtools/build/lib/authandtls/credentialhelper/CredentialHelperTest.java
+++ b/src/test/java/com/google/devtools/build/lib/authandtls/credentialhelper/CredentialHelperTest.java
@@ -22,6 +22,7 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.eventbus.EventBus;
 import com.google.devtools.build.lib.events.Reporter;
+import com.google.devtools.build.lib.shell.WindowsSubprocessFactory;
 import com.google.devtools.build.lib.util.OS;
 import com.google.devtools.build.lib.vfs.FileSystem;
 import com.google.devtools.build.lib.vfs.PathFragment;
@@ -37,6 +38,10 @@
 
 @RunWith(JUnit4.class)
 public class CredentialHelperTest {
+  static {
+    WindowsSubprocessFactory.maybeInstallWindowsSubprocessFactory();
+  }
+
   private static final PathFragment TEST_WORKSPACE_PATH =
       PathFragment.create(System.getenv("TEST_TMPDIR"));
   private static final PathFragment TEST_CREDENTIAL_HELPER_PATH =
diff --git a/src/test/java/com/google/devtools/build/lib/buildtool/util/BUILD b/src/test/java/com/google/devtools/build/lib/buildtool/util/BUILD
index f12466c..aef79b4 100644
--- a/src/test/java/com/google/devtools/build/lib/buildtool/util/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/buildtool/util/BUILD
@@ -78,9 +78,7 @@
         "//src/main/java/com/google/devtools/build/lib/pkgcache",
         "//src/main/java/com/google/devtools/build/lib/pkgcache:package_options",
         "//src/main/java/com/google/devtools/build/lib/profiler",
-        "//src/main/java/com/google/devtools/build/lib/profiler:collect_local_resource_usage",
         "//src/main/java/com/google/devtools/build/lib/profiler:profiler_impl",
-        "//src/main/java/com/google/devtools/build/lib/profiler:system_network_stats_service",
         "//src/main/java/com/google/devtools/build/lib/profiler:system_network_stats_service_impl",
         "//src/main/java/com/google/devtools/build/lib/query2",
         "//src/main/java/com/google/devtools/build/lib/query2/engine",
@@ -88,6 +86,7 @@
         "//src/main/java/com/google/devtools/build/lib/sandbox:sandbox_module",
         "//src/main/java/com/google/devtools/build/lib/sandbox:sandbox_options",
         "//src/main/java/com/google/devtools/build/lib/shell",
+        "//src/main/java/com/google/devtools/build/lib/shell:windows_subprocess_factory",
         "//src/main/java/com/google/devtools/build/lib/skyframe:action_execution_value",
         "//src/main/java/com/google/devtools/build/lib/skyframe:build_result_listener",
         "//src/main/java/com/google/devtools/build/lib/skyframe:configured_target_and_data",
@@ -106,7 +105,6 @@
         "//src/main/java/com/google/devtools/build/lib/vfs",
         "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
         "//src/main/java/com/google/devtools/build/lib/worker:worker_module",
-        "//src/main/java/com/google/devtools/build/lib/worker:worker_process_metrics",
         "//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
         "//src/main/java/com/google/devtools/common/options",
         "//src/main/java/com/google/devtools/common/options:invocation_policy",
diff --git a/src/test/java/com/google/devtools/build/lib/buildtool/util/BuildIntegrationTestCase.java b/src/test/java/com/google/devtools/build/lib/buildtool/util/BuildIntegrationTestCase.java
index 65b9cc6..b3bec68 100644
--- a/src/test/java/com/google/devtools/build/lib/buildtool/util/BuildIntegrationTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/buildtool/util/BuildIntegrationTestCase.java
@@ -116,6 +116,7 @@
 import com.google.devtools.build.lib.shell.AbnormalTerminationException;
 import com.google.devtools.build.lib.shell.Command;
 import com.google.devtools.build.lib.shell.CommandException;
+import com.google.devtools.build.lib.shell.WindowsSubprocessFactory;
 import com.google.devtools.build.lib.skyframe.ActionExecutionValue;
 import com.google.devtools.build.lib.skyframe.BuildResultListener;
 import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
@@ -187,6 +188,9 @@
  * <p>All integration tests are at least size medium.
  */
 public abstract class BuildIntegrationTestCase {
+  static {
+    WindowsSubprocessFactory.maybeInstallWindowsSubprocessFactory();
+  }
 
   /** Thrown when an integration test case fails. */
   public static class IntegrationTestExecException extends ExecException {
diff --git a/src/test/java/com/google/devtools/build/lib/shell/BUILD b/src/test/java/com/google/devtools/build/lib/shell/BUILD
index 085d87d..df1cf34 100644
--- a/src/test/java/com/google/devtools/build/lib/shell/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/shell/BUILD
@@ -201,6 +201,7 @@
     ],
     deps = [
         "//src/main/java/com/google/devtools/build/lib/shell",
+        "//src/main/java/com/google/devtools/build/lib/shell:windows_subprocess_factory",
         "//src/main/java/com/google/devtools/build/lib/util:os",
         "//third_party:guava",
         "//third_party:junit4",
diff --git a/src/test/java/com/google/devtools/build/lib/shell/LoadTest.java b/src/test/java/com/google/devtools/build/lib/shell/LoadTest.java
index 22bb8b5..4852d96 100644
--- a/src/test/java/com/google/devtools/build/lib/shell/LoadTest.java
+++ b/src/test/java/com/google/devtools/build/lib/shell/LoadTest.java
@@ -34,6 +34,9 @@
 /** Tests {@link Command} execution under load. */
 @RunWith(JUnit4.class)
 public class LoadTest {
+  static {
+    WindowsSubprocessFactory.maybeInstallWindowsSubprocessFactory();
+  }
 
   private File tempFile;
 
diff --git a/src/test/java/com/google/devtools/build/lib/standalone/BUILD b/src/test/java/com/google/devtools/build/lib/standalone/BUILD
index 6ec4728..753ccb4 100644
--- a/src/test/java/com/google/devtools/build/lib/standalone/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/standalone/BUILD
@@ -33,6 +33,7 @@
         "//src/main/java/com/google/devtools/build/lib/exec:spawn_strategy_resolver",
         "//src/main/java/com/google/devtools/build/lib/exec/local",
         "//src/main/java/com/google/devtools/build/lib/exec/local:options",
+        "//src/main/java/com/google/devtools/build/lib/shell:windows_subprocess_factory",
         "//src/main/java/com/google/devtools/build/lib/standalone",
         "//src/main/java/com/google/devtools/build/lib/util:os",
         "//src/main/java/com/google/devtools/build/lib/util/io",
diff --git a/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java b/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
index 66fded9..3f3fcd5 100644
--- a/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
@@ -53,6 +53,7 @@
 import com.google.devtools.build.lib.exec.local.LocalSpawnRunner;
 import com.google.devtools.build.lib.exec.util.TestExecutorBuilder;
 import com.google.devtools.build.lib.integration.util.IntegrationMock;
+import com.google.devtools.build.lib.shell.WindowsSubprocessFactory;
 import com.google.devtools.build.lib.testutil.TestConstants;
 import com.google.devtools.build.lib.testutil.TestUtils;
 import com.google.devtools.build.lib.util.OS;
@@ -76,6 +77,10 @@
 /** Test StandaloneSpawnStrategy. */
 @RunWith(JUnit4.class)
 public class StandaloneSpawnStrategyTest {
+  static {
+    WindowsSubprocessFactory.maybeInstallWindowsSubprocessFactory();
+  }
+
   private static final String WINDOWS_SYSTEM_DRIVE = "C:";
   private static final String CMD_EXE = getWinSystemBinary("cmd.exe");
 
diff --git a/src/test/java/com/google/devtools/build/lib/testutil/BUILD b/src/test/java/com/google/devtools/build/lib/testutil/BUILD
index 3ce64d4..f551b58 100644
--- a/src/test/java/com/google/devtools/build/lib/testutil/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/testutil/BUILD
@@ -142,6 +142,7 @@
     data = [":external_file_system_lock_helper"],
     deps = [
         "//src/main/java/com/google/devtools/build/lib/shell",
+        "//src/main/java/com/google/devtools/build/lib/shell:windows_subprocess_factory",
         "//src/main/java/com/google/devtools/build/lib/util:os",
         "//src/main/java/com/google/devtools/build/lib/vfs",
         "//third_party:guava",
diff --git a/src/test/java/com/google/devtools/build/lib/testutil/ExternalFileSystemLock.java b/src/test/java/com/google/devtools/build/lib/testutil/ExternalFileSystemLock.java
index eca7dd2..d29e527 100644
--- a/src/test/java/com/google/devtools/build/lib/testutil/ExternalFileSystemLock.java
+++ b/src/test/java/com/google/devtools/build/lib/testutil/ExternalFileSystemLock.java
@@ -16,6 +16,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.shell.Subprocess;
 import com.google.devtools.build.lib.shell.SubprocessBuilder;
+import com.google.devtools.build.lib.shell.WindowsSubprocessFactory;
 import com.google.devtools.build.lib.util.OS;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.runfiles.Runfiles;
@@ -27,6 +28,10 @@
  * <p>This is needed for testing because the JVM does not allow overlapping locks.
  */
 public class ExternalFileSystemLock implements AutoCloseable {
+  static {
+    WindowsSubprocessFactory.maybeInstallWindowsSubprocessFactory();
+  }
+
   private static final String HELPER_PATH =
       "io_bazel/src/test/java/com/google/devtools/build/lib/testutil/external_file_system_lock_helper"
           + (OS.getCurrent() == OS.WINDOWS ? ".exe" : "");
diff --git a/src/test/java/com/google/devtools/build/lib/windows/BUILD b/src/test/java/com/google/devtools/build/lib/windows/BUILD
index c0c6377..b0e5e0c0 100644
--- a/src/test/java/com/google/devtools/build/lib/windows/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/windows/BUILD
@@ -36,6 +36,7 @@
     ],
     deps = [
         "//src/main/java/com/google/devtools/build/lib/shell",
+        "//src/main/java/com/google/devtools/build/lib/shell:windows_subprocess_factory",
         "//src/main/java/com/google/devtools/build/lib/skyframe:default_syscall_cache",
         "//src/main/java/com/google/devtools/build/lib/util:os",
         "//src/main/java/com/google/devtools/build/lib/util:string_encoding",
diff --git a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/BUILD b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/BUILD
index 2614795..5227bb8 100644
--- a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/BUILD
+++ b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/BUILD
@@ -42,6 +42,7 @@
         "//src/main/java/com/google/devtools/build/lib/remote/util:digest_utils",
         "//src/main/java/com/google/devtools/build/lib/sandbox:linux_sandbox_command_line_builder",
         "//src/main/java/com/google/devtools/build/lib/shell",
+        "//src/main/java/com/google/devtools/build/lib/shell:windows_subprocess_factory",
         "//src/main/java/com/google/devtools/build/lib/unix",
         "//src/main/java/com/google/devtools/build/lib/util:os",
         "//src/main/java/com/google/devtools/build/lib/util:resource_converter",
diff --git a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java
index dc646bb..f2fbced 100644
--- a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java
+++ b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java
@@ -37,6 +37,7 @@
 import com.google.devtools.build.lib.shell.Command;
 import com.google.devtools.build.lib.shell.CommandException;
 import com.google.devtools.build.lib.shell.CommandResult;
+import com.google.devtools.build.lib.shell.WindowsSubprocessFactory;
 import com.google.devtools.build.lib.unix.UnixFileSystem;
 import com.google.devtools.build.lib.util.OS;
 import com.google.devtools.build.lib.util.SingleLineFormatter;
@@ -306,6 +307,10 @@
     // about closed streams around.
     nettyLogger.setLevel(Level.SEVERE);
 
+    // Set the default subprocess factory to the Windows-specific implementation if the host OS is
+    // Windows. See Bazel.java for more details.
+    WindowsSubprocessFactory.maybeInstallWindowsSubprocessFactory();
+
     FileSystem fs = getFileSystem();
     Path sandboxPath = null;
     if (remoteWorkerOptions.sandboxing) {