Allow Skyframe graph lookups and value retrievals to throw InterruptedException.

The only place we now don't handle InterruptedException is in the action graph created after analysis, since I'm not sure that will be around for that much longer.

--
MOS_MIGRATED_REVID=130327770
diff --git a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java
index 00f918a..8bd3f44 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java
@@ -32,10 +32,8 @@
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.lib.vfs.Symlinks;
-
 import java.io.IOException;
 import java.util.Collection;
-
 import javax.annotation.Nullable;
 
 /**
@@ -154,9 +152,11 @@
 
   @Nullable
   @Override
-  public Iterable<Artifact> resolveInputsFromCache(ArtifactResolver artifactResolver,
-      PackageRootResolver resolver, Collection<PathFragment> inputPaths)
-          throws PackageRootResolutionException {
+  public Iterable<Artifact> resolveInputsFromCache(
+      ArtifactResolver artifactResolver,
+      PackageRootResolver resolver,
+      Collection<PathFragment> inputPaths)
+      throws PackageRootResolutionException, InterruptedException {
     throw new IllegalStateException(
         "Method must be overridden for actions that may have unknown inputs.");
   }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Action.java b/src/main/java/com/google/devtools/build/lib/actions/Action.java
index 01cf554..d7623de 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Action.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/Action.java
@@ -19,10 +19,8 @@
 import com.google.devtools.build.lib.profiler.Describable;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.io.IOException;
 import java.util.Collection;
-
 import javax.annotation.Nullable;
 
 /**
@@ -154,25 +152,25 @@
       throws ActionExecutionException, InterruptedException;
 
   /**
-   * Method used to resolve action inputs based on the information contained in
-   * the action cache. It will be called iff inputsKnown() is false for the
-   * given action instance and there is a related cache entry in the action
-   * cache.
+   * Method used to resolve action inputs based on the information contained in the action cache. It
+   * will be called iff inputsKnown() is false for the given action instance and there is a related
+   * cache entry in the action cache.
    *
-   * Method must be redefined for any action that may return
-   * inputsKnown() == false.
+   * <p>Method must be redefined for any action that may return inputsKnown() == false.
    *
    * @param artifactResolver the artifact factory that can be used to manufacture artifacts
    * @param resolver object which helps to resolve some of the artifacts
    * @param inputPaths List of relative (to the execution root) input paths
    * @return List of Artifacts corresponding to inputPaths, or null if some dependencies were
-   * missing and we need to try again later.
+   *     missing and we need to try again later.
    * @throws PackageRootResolutionException on failure to determine package roots of inputPaths
    */
   @Nullable
   Iterable<Artifact> resolveInputsFromCache(
-      ArtifactResolver artifactResolver, PackageRootResolver resolver,
-      Collection<PathFragment> inputPaths) throws PackageRootResolutionException;
+      ArtifactResolver artifactResolver,
+      PackageRootResolver resolver,
+      Collection<PathFragment> inputPaths)
+      throws PackageRootResolutionException, InterruptedException;
 
   /**
    * Informs the action that its inputs are {@code inputs}, and that its inputs are now known. Can
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java b/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java
index 86cbd0a..b96a9e4 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java
@@ -27,13 +27,11 @@
 import com.google.devtools.build.lib.events.EventKind;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -242,7 +240,7 @@
 
   @Nullable
   public Iterable<Artifact> getCachedInputs(Action action, PackageRootResolver resolver)
-      throws PackageRootResolutionException {
+      throws PackageRootResolutionException, InterruptedException {
     ActionCache.Entry entry = getCacheEntry(action);
     if (entry == null || entry.isCorrupted()) {
       return ImmutableList.of();
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java b/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java
index 1606c0e..941ea15 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java
@@ -26,13 +26,11 @@
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
-
 import javax.annotation.Nullable;
 
 /**
@@ -369,7 +367,7 @@
   @Override
   public synchronized Map<PathFragment, Artifact> resolveSourceArtifacts(
       Iterable<PathFragment> execPaths, PackageRootResolver resolver)
-          throws PackageRootResolutionException {
+      throws PackageRootResolutionException, InterruptedException {
     Map<PathFragment, Artifact> result = new HashMap<>();
     ArrayList<PathFragment> unresolvedPaths = new ArrayList<>();
 
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java b/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java
index e7ea2f2..58b36c9 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java
@@ -15,9 +15,7 @@
 package com.google.devtools.build.lib.actions;
 
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -69,12 +67,13 @@
    * @param execPaths list of exec paths of the artifacts to resolve
    * @param resolver object that helps to resolve package root of given paths
    * @return map which contains list of execPaths and corresponding Artifacts. Map can contain
-   *         existing or new source Artifacts for the given execPaths. The artifact is null if the
-   *         root cannot be determined and the artifact did not exist before. Return null if any
-   *         dependencies are missing.
+   *     existing or new source Artifacts for the given execPaths. The artifact is null if the root
+   *     cannot be determined and the artifact did not exist before. Return null if any dependencies
+   *     are missing.
    * @throws PackageRootResolutionException failure to determine package roots of {@code execPaths}
    */
   @Nullable
-  Map<PathFragment, Artifact> resolveSourceArtifacts(Iterable<PathFragment> execPaths,
-      PackageRootResolver resolver) throws PackageRootResolutionException;
+  Map<PathFragment, Artifact> resolveSourceArtifacts(
+      Iterable<PathFragment> execPaths, PackageRootResolver resolver)
+      throws PackageRootResolutionException, InterruptedException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java b/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java
index 0db0075..2b7a3ca 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java
@@ -15,9 +15,7 @@
 package com.google.devtools.build.lib.actions;
 
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -26,34 +24,33 @@
 public interface PackageRootResolver {
 
   /**
-   * Returns mapping from execPath to Root. Root will be null if the path has no containing
-   * package.
+   * Returns mapping from execPath to Root. Root will be null if the path has no containing package.
    *
    * @param execPaths the paths to find {@link Root}s for. The search for a containing package will
-   *    start with the path's parent directory, since the path is assumed to be a file.
-   * @return mappings from {@code execPath} to {@link Root}, or null if for some reason we
-   *    cannot determine the result at this time (such as when used within a SkyFunction)
+   *     start with the path's parent directory, since the path is assumed to be a file.
+   * @return mappings from {@code execPath} to {@link Root}, or null if for some reason we cannot
+   *     determine the result at this time (such as when used within a SkyFunction)
    * @throws PackageRootResolutionException if unable to determine package roots or lack thereof,
-   *    typically caused by exceptions encountered while attempting to locate BUILD files
+   *     typically caused by exceptions encountered while attempting to locate BUILD files
    */
   @Nullable
   Map<PathFragment, Root> findPackageRootsForFiles(Iterable<PathFragment> execPaths)
-      throws PackageRootResolutionException;
+      throws PackageRootResolutionException, InterruptedException;
 
   /**
-   * Returns mapping from execPath to Root. Root will be null if the path has no containing
-   * package. Unlike {@link #findPackageRootsForFiles(Iterable)}, this function allows directories
-   * in the list of exec paths.
+   * Returns mapping from execPath to Root. Root will be null if the path has no containing package.
+   * Unlike {@link #findPackageRootsForFiles(Iterable)}, this function allows directories in the
+   * list of exec paths.
    *
    * @param execPaths the paths to find {@link Root}s for. The search for a containing package will
-   *    start with the path's parent directory, since the path is assumed to be a file.
-   * @return mappings from {@code execPath} to {@link Root}, or null if for some reason we
-   *    cannot determine the result at this time (such as when used within a SkyFunction)
+   *     start with the path's parent directory, since the path is assumed to be a file.
+   * @return mappings from {@code execPath} to {@link Root}, or null if for some reason we cannot
+   *     determine the result at this time (such as when used within a SkyFunction)
    * @throws PackageRootResolutionException if unable to determine package roots or lack thereof,
-   *    typically caused by exceptions encountered while attempting to locate BUILD files
+   *     typically caused by exceptions encountered while attempting to locate BUILD files
    */
   // TODO(bazel-team): Remove this once we don't need to find package roots for directories.
   @Nullable
   Map<PathFragment, Root> findPackageRoots(Iterable<PathFragment> execPaths)
-      throws PackageRootResolutionException;
+      throws PackageRootResolutionException, InterruptedException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
index fcdc3ec..9f9a655 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
@@ -127,13 +127,13 @@
    * Returns the Artifact that is used to hold the non-volatile workspace status for the current
    * build request.
    */
-  Artifact getStableWorkspaceStatusArtifact();
+  Artifact getStableWorkspaceStatusArtifact() throws InterruptedException;
 
   /**
-   * Returns the Artifact that is used to hold the volatile workspace status (e.g. build
-   * changelist) for the current build request.
+   * Returns the Artifact that is used to hold the volatile workspace status (e.g. build changelist)
+   * for the current build request.
    */
-  Artifact getVolatileWorkspaceStatusArtifact();
+  Artifact getVolatileWorkspaceStatusArtifact() throws InterruptedException;
 
   /**
    * Returns the Artifacts that contain the workspace status for the current build request.
@@ -142,7 +142,8 @@
    * @param config the current build configuration.
    */
   ImmutableList<Artifact> getBuildInfo(
-      RuleContext ruleContext, BuildInfoKey key, BuildConfiguration config);
+      RuleContext ruleContext, BuildInfoKey key, BuildConfiguration config)
+      throws InterruptedException;
 
   /**
    * Returns the set of orphan Artifacts (i.e. Artifacts without generating action). Should only be
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
index 5fed4a3..8b5eb24 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
@@ -81,7 +81,6 @@
 import com.google.devtools.build.skyframe.WalkableGraph;
 import com.google.devtools.common.options.Option;
 import com.google.devtools.common.options.OptionsBase;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -568,19 +567,26 @@
     String error = createErrorMessage(loadingResult, skyframeAnalysisResult);
 
     final WalkableGraph graph = skyframeAnalysisResult.getWalkableGraph();
-    final ActionGraph actionGraph = new ActionGraph() {
-      @Nullable
-      @Override
-      public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) {
-        ArtifactOwner artifactOwner = artifact.getArtifactOwner();
-        if (artifactOwner instanceof ActionLookupValue.ActionLookupKey) {
-          SkyKey key = ActionLookupValue.key((ActionLookupValue.ActionLookupKey) artifactOwner);
-          ActionLookupValue val = (ActionLookupValue) graph.getValue(key);
-          return val == null ? null : val.getGeneratingAction(artifact);
-        }
-        return null;
-      }
-    };
+    final ActionGraph actionGraph =
+        new ActionGraph() {
+          @Nullable
+          @Override
+          public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) {
+            ArtifactOwner artifactOwner = artifact.getArtifactOwner();
+            if (artifactOwner instanceof ActionLookupValue.ActionLookupKey) {
+              SkyKey key = ActionLookupValue.key((ActionLookupValue.ActionLookupKey) artifactOwner);
+              ActionLookupValue val;
+              try {
+                val = (ActionLookupValue) graph.getValue(key);
+              } catch (InterruptedException e) {
+                throw new IllegalStateException(
+                    "Interruption not expected from this graph: " + key, e);
+              }
+              return val == null ? null : val.getGeneratingAction(artifact);
+            }
+            return null;
+          }
+        };
     return new AnalysisResult(
         configuredTargets,
         aspects,
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
index 5fd3d43..5aed23d 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
@@ -37,7 +37,6 @@
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.skyframe.SkyFunction;
-
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
@@ -49,7 +48,6 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
-
 import javax.annotation.Nullable;
 
 /**
@@ -287,21 +285,21 @@
   }
 
   @Override
-  public Artifact getStableWorkspaceStatusArtifact() {
+  public Artifact getStableWorkspaceStatusArtifact() throws InterruptedException {
     return ((WorkspaceStatusValue) skyframeEnv.getValue(WorkspaceStatusValue.SKY_KEY))
             .getStableArtifact();
   }
 
   @Override
-  public Artifact getVolatileWorkspaceStatusArtifact() {
+  public Artifact getVolatileWorkspaceStatusArtifact() throws InterruptedException {
     return ((WorkspaceStatusValue) skyframeEnv.getValue(WorkspaceStatusValue.SKY_KEY))
             .getVolatileArtifact();
   }
 
   // See SkyframeBuildView#getWorkspaceStatusValues for the code that this method is attempting to
   // verify.
-  private NullPointerException collectDebugInfoAndCrash(
-      BuildInfoKey key, BuildConfiguration config) {
+  private NullPointerException collectDebugInfoAndCrash(BuildInfoKey key, BuildConfiguration config)
+      throws InterruptedException {
     String debugInfo = key + " " + config;
     Preconditions.checkState(skyframeEnv.valuesMissing(), debugInfo);
     Map<BuildInfoKey, BuildInfoFactory> buildInfoFactories = Preconditions.checkNotNull(
@@ -314,7 +312,8 @@
 
   @Override
   public ImmutableList<Artifact> getBuildInfo(
-      RuleContext ruleContext, BuildInfoKey key, BuildConfiguration config) {
+      RuleContext ruleContext, BuildInfoKey key, BuildConfiguration config)
+      throws InterruptedException {
     boolean stamp = AnalysisUtils.isStampingEnabled(ruleContext, config);
     BuildInfoCollectionValue collectionValue =
         (BuildInfoCollectionValue) skyframeEnv.getValue(BuildInfoCollectionValue.key(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java
index 77c51d9..75ac3a0 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java
@@ -21,7 +21,6 @@
 import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
 import com.google.devtools.build.lib.analysis.config.PackageProviderForConfigurations;
 import com.google.devtools.build.lib.events.EventHandler;
-
 import javax.annotation.Nullable;
 
 /**
@@ -31,9 +30,10 @@
   /**
    * Creates the top-level configuration for a build.
    *
-   * <p>Also it may create a set of BuildConfigurations and define a transition table over them.
-   * All configurations during a build should be accessible from this top-level configuration
-   * via configuration transitions.
+   * <p>Also it may create a set of BuildConfigurations and define a transition table over them. All
+   * configurations during a build should be accessible from this top-level configuration via
+   * configuration transitions.
+   *
    * @param configurationFactory the configuration factory
    * @param cache a cache for BuildConfigurations
    * @param loadedPackageProvider the package provider
@@ -48,7 +48,8 @@
       Cache<String, BuildConfiguration> cache,
       PackageProviderForConfigurations loadedPackageProvider,
       BuildOptions buildOptions,
-      EventHandler errorEventListener) throws InvalidConfigurationException;
+      EventHandler errorEventListener)
+      throws InvalidConfigurationException, InterruptedException;
 
   /**
    * Returns the module the given configuration should use for choosing dynamic transitions.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
index 6816b42..10703ba 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
@@ -45,14 +45,12 @@
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.util.OrderedSetMultimap;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -232,12 +230,15 @@
     }
   }
 
-  private void resolveExplicitAttributes(final RuleResolver depResolver) {
+  private void resolveExplicitAttributes(final RuleResolver depResolver)
+      throws InterruptedException {
     depResolver.attributeMap.visitLabels(
         new AttributeMap.AcceptsLabelAttribute() {
           @Override
-          public void acceptLabelAttribute(Label label, Attribute attribute) {
-            if (attribute.getType() == BuildType.NODEP_LABEL || attribute.isImplicit()
+          public void acceptLabelAttribute(Label label, Attribute attribute)
+              throws InterruptedException {
+            if (attribute.getType() == BuildType.NODEP_LABEL
+                || attribute.isImplicit()
                 || attribute.isLateBound()) {
               return;
             }
@@ -246,10 +247,8 @@
         });
   }
 
-  /**
-   * Resolves the dependencies for all implicit attributes in this rule.
-   */
-  private void resolveImplicitAttributes(RuleResolver depResolver) {
+  /** Resolves the dependencies for all implicit attributes in this rule. */
+  private void resolveImplicitAttributes(RuleResolver depResolver) throws InterruptedException {
     // Since the attributes that come from aspects do not appear in attributeMap, we have to get
     // their values from somewhere else. This incidentally means that aspects attributes are not
     // configurable. It would be nice if that wasn't the case, but we'd have to revamp how
@@ -455,7 +454,8 @@
    * @param attrName the name of the attribute to add dependency labels to
    * @param labels the dependencies to add
    */
-  private void addExplicitDeps(RuleResolver depResolver, String attrName, Iterable<Label> labels) {
+  private void addExplicitDeps(RuleResolver depResolver, String attrName, Iterable<Label> labels)
+      throws InterruptedException {
     Rule rule = depResolver.rule;
     if (!rule.isAttrDefined(attrName, BuildType.LABEL_LIST)
         && !rule.isAttrDefined(attrName, BuildType.NODEP_LABEL_LIST)) {
@@ -468,13 +468,16 @@
   }
 
   /**
-   * Converts the given multimap of attributes to labels into a multi map of attributes to
-   * {@link Dependency} objects using the proper configuration transition for each attribute.
+   * Converts the given multimap of attributes to labels into a multi map of attributes to {@link
+   * Dependency} objects using the proper configuration transition for each attribute.
    *
    * @throws IllegalArgumentException if the {@code node} does not refer to a {@link Rule} instance
    */
-  public final Collection<Dependency> resolveRuleLabels(TargetAndConfiguration node,
-      OrderedSetMultimap<Attribute, Label> depLabels, NestedSetBuilder<Label> rootCauses) {
+  public final Collection<Dependency> resolveRuleLabels(
+      TargetAndConfiguration node,
+      OrderedSetMultimap<Attribute, Label> depLabels,
+      NestedSetBuilder<Label> rootCauses)
+      throws InterruptedException {
     Preconditions.checkArgument(node.getTarget() instanceof Rule);
     Rule rule = (Rule) node.getTarget();
     OrderedSetMultimap<Attribute, Dependency> outgoingEdges = OrderedSetMultimap.create();
@@ -489,8 +492,12 @@
     return outgoingEdges.values();
   }
 
-  private void visitPackageGroup(TargetAndConfiguration node, PackageGroup packageGroup,
-      NestedSetBuilder<Label> rootCauses, Collection<Dependency> outgoingEdges) {
+  private void visitPackageGroup(
+      TargetAndConfiguration node,
+      PackageGroup packageGroup,
+      NestedSetBuilder<Label> rootCauses,
+      Collection<Dependency> outgoingEdges)
+      throws InterruptedException {
     for (Label label : packageGroup.getIncludes()) {
       Target target = getTarget(packageGroup, label, rootCauses);
       if (target == null) {
@@ -508,7 +515,7 @@
     }
   }
 
-  private ImmutableSet<AspectDescriptor> requiredAspects(
+  private static ImmutableSet<AspectDescriptor> requiredAspects(
       @Nullable Aspect aspect, Attribute attribute, final Target target, Rule originalRule) {
     if (!(target instanceof Rule)) {
       return ImmutableSet.of();
@@ -613,10 +620,10 @@
     }
 
     /**
-     * Resolves the given dep for the given attribute, including determining which
-     * configurations to apply to it.
+     * Resolves the given dep for the given attribute, including determining which configurations to
+     * apply to it.
      */
-    void resolveDep(Attribute attribute, Label depLabel) {
+    void resolveDep(Attribute attribute, Label depLabel) throws InterruptedException {
       Target toTarget = getTarget(rule, depLabel, rootCauses);
       if (toTarget == null) {
         return; // Skip this round: we still need to Skyframe-evaluate the dep's target.
@@ -633,13 +640,14 @@
     /**
      * Resolves the given dep for the given attribute using a pre-prepared configuration.
      *
-     * <p>Use this method with care: it skips Bazel's standard config transition semantics
-     * ({@link BuildConfiguration#evaluateTransition}). That means attributes passed through here
-     * won't obey standard rules on which configurations apply to their deps. This should only
-     * be done for special circumstances that really justify the difference. When in doubt, use
-     * {@link #resolveDep(Attribute, Label)}.
+     * <p>Use this method with care: it skips Bazel's standard config transition semantics ({@link
+     * BuildConfiguration#evaluateTransition}). That means attributes passed through here won't obey
+     * standard rules on which configurations apply to their deps. This should only be done for
+     * special circumstances that really justify the difference. When in doubt, use {@link
+     * #resolveDep(Attribute, Label)}.
      */
-    void resolveDep(Attribute attribute, Label depLabel, BuildConfiguration config) {
+    void resolveDep(Attribute attribute, Label depLabel, BuildConfiguration config)
+        throws InterruptedException {
       Target toTarget = getTarget(rule, depLabel, rootCauses);
       if (toTarget == null) {
         return; // Skip this round: this is either a loading error or unevaluated Skyframe dep.
@@ -686,8 +694,11 @@
     }
   }
 
-  private void visitTargetVisibility(TargetAndConfiguration node,
-      NestedSetBuilder<Label> rootCauses, Collection<Dependency> outgoingEdges) {
+  private void visitTargetVisibility(
+      TargetAndConfiguration node,
+      NestedSetBuilder<Label> rootCauses,
+      Collection<Dependency> outgoingEdges)
+      throws InterruptedException {
     Target target = node.getTarget();
     for (Label label : target.getVisibility().getDependencyLabels()) {
       Target visibilityTarget = getTarget(target, label, rootCauses);
@@ -733,22 +744,24 @@
    * @param to the missing target
    * @param e the exception that was thrown, e.g., by {@link #getTarget}
    */
-  protected abstract void missingEdgeHook(Target from, Label to, NoSuchThingException e);
+  protected abstract void missingEdgeHook(Target from, Label to, NoSuchThingException e)
+      throws InterruptedException;
 
   /**
    * Returns the target by the given label.
    *
    * <p>Returns null if the target is not ready to be returned at this moment. If getTarget returns
    * null once or more during a {@link #dependentNodeMap} call, the results of that call will be
-   * incomplete. For use within Skyframe, where several iterations may be needed to discover
-   * all dependencies.
+   * incomplete. For use within Skyframe, where several iterations may be needed to discover all
+   * dependencies.
    */
   @Nullable
-  protected abstract Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses);
+  protected abstract Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses)
+      throws InterruptedException;
 
   /**
-   * Returns the build configurations with the given options and fragments, in the same order as
-   * the input options.
+   * Returns the build configurations with the given options and fragments, in the same order as the
+   * input options.
    *
    * <p>Returns null if any configurations aren't ready to be returned at this moment. If
    * getConfigurations returns null once or more during a {@link #dependentNodeMap} call, the
@@ -758,5 +771,6 @@
   @Nullable
   protected abstract List<BuildConfiguration> getConfigurations(
       Set<Class<? extends BuildConfiguration.Fragment>> fragments,
-      Iterable<BuildOptions> buildOptions) throws InvalidConfigurationException;
+      Iterable<BuildOptions> buildOptions)
+      throws InvalidConfigurationException, InterruptedException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RedirectChaser.java b/src/main/java/com/google/devtools/build/lib/analysis/RedirectChaser.java
index a908ada..6a27b5c 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RedirectChaser.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RedirectChaser.java
@@ -71,7 +71,7 @@
    */
   @Nullable
   public static Label followRedirects(ConfigurationEnvironment env, Label label, String name)
-      throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     Label oldLabel = null;
     Set<Label> visitedLabels = new HashSet<>();
     visitedLabels.add(label);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 321c385..a829195 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -391,7 +391,7 @@
     return getAnalysisEnvironment().getOwner();
   }
 
-  public ImmutableList<Artifact> getBuildInfo(BuildInfoKey key) {
+  public ImmutableList<Artifact> getBuildInfo(BuildInfoKey key) throws InterruptedException {
     return getAnalysisEnvironment().getBuildInfo(this, key, getConfiguration());
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationEnvironment.java
index d2439ac..ec55f60 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationEnvironment.java
@@ -24,9 +24,7 @@
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.pkgcache.LoadedPackageProvider;
 import com.google.devtools.build.lib.pkgcache.PackageProvider;
-import com.google.devtools.build.lib.pkgcache.TargetProvider;
 import com.google.devtools.build.lib.vfs.Path;
-
 import javax.annotation.Nullable;
 
 /**
@@ -48,18 +46,19 @@
    *
    * @see TargetProvider#getTarget
    */
-  Target getTarget(Label label) throws NoSuchPackageException, NoSuchTargetException;
+  Target getTarget(Label label)
+      throws NoSuchPackageException, NoSuchTargetException, InterruptedException;
 
   /** Returns a path for the given file within the given package. */
-  Path getPath(Package pkg, String fileName);
-  
+  Path getPath(Package pkg, String fileName) throws InterruptedException;
+
   /** Returns fragment based on fragment class and build options. */
-  <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType) 
-      throws InvalidConfigurationException;
+  <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType)
+      throws InvalidConfigurationException, InterruptedException;
 
   /** Returns global value of BlazeDirectories. */
   @Nullable
-  BlazeDirectories getBlazeDirectories();
+  BlazeDirectories getBlazeDirectories() throws InterruptedException;
 
   /**
    * An implementation backed by a {@link PackageProvider} instance.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java
index 31eb150..595f527 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java
@@ -22,11 +22,9 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -69,23 +67,27 @@
   @Nullable
   public BuildConfiguration createConfigurations(
       Cache<String, BuildConfiguration> cache,
-      PackageProviderForConfigurations loadedPackageProvider, BuildOptions buildOptions,
+      PackageProviderForConfigurations loadedPackageProvider,
+      BuildOptions buildOptions,
       EventHandler errorEventListener)
-          throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     return configurationCollectionFactory.createConfigurations(this, cache,
         loadedPackageProvider, buildOptions, errorEventListener);
   }
 
   /**
-   * Returns a {@link com.google.devtools.build.lib.analysis.config.BuildConfiguration} based on
-   * the given set of build options.
+   * Returns a {@link com.google.devtools.build.lib.analysis.config.BuildConfiguration} based on the
+   * given set of build options.
    *
    * <p>If the configuration has already been created, re-uses it, otherwise, creates a new one.
    */
   @Nullable
-  public BuildConfiguration getConfiguration(PackageProviderForConfigurations loadedPackageProvider,
-      BuildOptions buildOptions, boolean actionsDisabled, Cache<String, BuildConfiguration> cache)
-      throws InvalidConfigurationException {
+  public BuildConfiguration getConfiguration(
+      PackageProviderForConfigurations loadedPackageProvider,
+      BuildOptions buildOptions,
+      boolean actionsDisabled,
+      Cache<String, BuildConfiguration> cache)
+      throws InvalidConfigurationException, InterruptedException {
 
     String cacheKey = buildOptions.computeCacheKey();
     BuildConfiguration result = cache.getIfPresent(cacheKey);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFragmentFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFragmentFactory.java
index 1ae9a66..0c19502 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFragmentFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFragmentFactory.java
@@ -15,7 +15,6 @@
 
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment;
-
 import javax.annotation.Nullable;
 
 /**
@@ -31,7 +30,7 @@
    */
   @Nullable
   BuildConfiguration.Fragment create(ConfigurationEnvironment env, BuildOptions buildOptions)
-      throws InvalidConfigurationException;
+      throws InvalidConfigurationException, InterruptedException;
 
   /**
    * @return the exact type of the fragment this factory creates.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/PackageProviderForConfigurations.java b/src/main/java/com/google/devtools/build/lib/analysis/config/PackageProviderForConfigurations.java
index dddc786..e493e48 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/PackageProviderForConfigurations.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/PackageProviderForConfigurations.java
@@ -22,7 +22,6 @@
 import com.google.devtools.build.lib.packages.NoSuchTargetException;
 import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.packages.Target;
-
 import java.io.IOException;
 
 /**
@@ -35,18 +34,15 @@
    * Adds dependency to fileName if needed. Used only in skyframe, for creating correct dependencies
    * for {@link com.google.devtools.build.lib.skyframe.ConfigurationCollectionValue}.
    */
-  void addDependency(Package pkg, String fileName) throws LabelSyntaxException, IOException;
-  
-  /**
-   * Returns fragment based on fragment type and build options.
-   */
-  <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType) 
-      throws InvalidConfigurationException;
-  
-  /**
-   * Returns blaze directories and adds dependency to that value.
-   */
-  BlazeDirectories getDirectories();
+  void addDependency(Package pkg, String fileName)
+      throws LabelSyntaxException, IOException, InterruptedException;
+
+  /** Returns fragment based on fragment type and build options. */
+  <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType)
+      throws InvalidConfigurationException, InterruptedException;
+
+  /** Returns blaze directories and adds dependency to that value. */
+  BlazeDirectories getDirectories() throws InterruptedException;
   
   /**
    * Returns true if any dependency is missing (value of some node hasn't been evaluated yet).
@@ -59,8 +55,9 @@
    * function evaluation.
    *
    * @throws NoSuchPackageException if the package could not be found
-   * @throws NoSuchTargetException if the package was loaded successfully, but
-   *         the specified {@link Target} was not found in it
+   * @throws NoSuchTargetException if the package was loaded successfully, but the specified {@link
+   *     Target} was not found in it
    */
-  Target getTarget(Label label) throws NoSuchPackageException, NoSuchTargetException;
+  Target getTarget(Label label)
+      throws NoSuchPackageException, NoSuchTargetException, InterruptedException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java
index 0ba5c0f..55c30dd 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java
@@ -23,10 +23,8 @@
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
-import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.io.IOException;
 
 /**
@@ -42,14 +40,13 @@
   @Override
   public SkyValue fetch(
       Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env)
-          throws SkyFunctionException {
+      throws InterruptedException, RepositoryFunctionException {
     createDirectory(outputDirectory, rule);
     GitCloner.clone(rule, outputDirectory, env.getListener(), clientEnvironment);
     return RepositoryDirectoryValue.create(outputDirectory);
   }
 
-  protected void createDirectory(Path path, Rule rule)
-      throws RepositoryFunctionException {
+  protected static void createDirectory(Path path, Rule rule) throws RepositoryFunctionException {
     try {
       FileSystemUtils.createDirectoryAndParents(path);
     } catch (IOException e) {
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java
index 28c4a00..a18b4e0 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java
@@ -23,12 +23,10 @@
 import com.google.devtools.build.lib.analysis.RuleDefinition;
 import com.google.devtools.build.lib.bazel.repository.downloader.HttpDownloader;
 import com.google.devtools.build.lib.bazel.rules.workspace.MavenJarRule;
-import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
 import com.google.devtools.build.lib.packages.AttributeMap;
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue;
-import com.google.devtools.build.lib.rules.repository.RepositoryFunction;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.util.Fingerprint;
@@ -36,7 +34,9 @@
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyValue;
-
+import java.io.IOException;
+import java.util.Map;
+import javax.annotation.Nullable;
 import org.apache.maven.settings.Server;
 import org.eclipse.aether.RepositorySystem;
 import org.eclipse.aether.RepositorySystemSession;
@@ -50,11 +50,6 @@
 import org.eclipse.aether.resolution.ArtifactResolutionException;
 import org.eclipse.aether.resolution.ArtifactResult;
 
-import java.io.IOException;
-import java.util.Map;
-
-import javax.annotation.Nullable;
-
 /**
  * Implementation of maven_jar.
  */
@@ -68,7 +63,7 @@
 
   @Override
   protected byte[] getRuleSpecificMarkerData(Rule rule, Environment env)
-      throws RepositoryFunctionException {
+      throws RepositoryFunctionException, InterruptedException {
     MavenServerValue serverValue = getServer(rule, env);
     if (env.valuesMissing()) {
       return null;
@@ -80,11 +75,11 @@
         .digestAndReset();
   }
 
-  private MavenServerValue getServer(Rule rule, Environment env)
-      throws RepositoryFunctionException {
+  private static MavenServerValue getServer(Rule rule, Environment env)
+      throws RepositoryFunctionException, InterruptedException {
     AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
-    boolean hasRepository = mapper.has("repository", Type.STRING)
-        && !mapper.get("repository", Type.STRING).isEmpty();
+    boolean hasRepository =
+        mapper.has("repository", Type.STRING) && !mapper.get("repository", Type.STRING).isEmpty();
     boolean hasServer = mapper.has("server", Type.STRING)
         && !mapper.get("server", Type.STRING).isEmpty();
 
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java
index 73bfe26..ea85f50 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java
@@ -31,12 +31,14 @@
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.lib.vfs.RootedPath;
 import com.google.devtools.build.skyframe.SkyFunction;
-import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyFunctionName;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Map;
+import javax.annotation.Nullable;
 import org.apache.maven.settings.Server;
 import org.apache.maven.settings.Settings;
 import org.apache.maven.settings.building.DefaultSettingsBuilder;
@@ -45,12 +47,6 @@
 import org.apache.maven.settings.building.SettingsBuildingException;
 import org.apache.maven.settings.building.SettingsBuildingResult;
 
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Map;
-
-import javax.annotation.Nullable;
-
 /**
  * Implementation of maven_repository.
  */
@@ -66,7 +62,7 @@
   @Nullable
   @Override
   public SkyValue compute(SkyKey skyKey, Environment env)
-      throws SkyFunctionException {
+      throws InterruptedException, RepositoryFunctionException {
     String repository = (String) skyKey.argument();
     Rule repositoryRule = null;
     try {
@@ -175,7 +171,7 @@
   }
 
   private Map<String, FileValue> getDefaultSettingsFile(
-      BlazeDirectories directories, Environment env) {
+      BlazeDirectories directories, Environment env) throws InterruptedException {
     // The system settings file is at $M2_HOME/conf/settings.xml.
     String m2Home = System.getenv("M2_HOME");
     ImmutableList.Builder<SkyKey> settingsFilesBuilder = ImmutableList.builder();
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java
index 4a8c56f..e41695f 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java
@@ -20,7 +20,6 @@
 import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
-import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyValue;
 
 /**
@@ -30,7 +29,7 @@
   @Override
   public SkyValue fetch(
       Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env)
-          throws SkyFunctionException { 
+      throws InterruptedException, RepositoryFunctionException {
     NewRepositoryBuildFileHandler buildFileHandler =
         new NewRepositoryBuildFileHandler(directories.getWorkspace());
     if (!buildFileHandler.prepareBuildFile(rule, env)) {
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
index 4ed66e9..bfe4aec 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
@@ -142,11 +142,12 @@
             + "during the analysis phase and thus cannot depends on a target result (the "
             + "label should point to a non-generated file)."
   )
-  public SkylarkPath path(Object path) throws EvalException {
+  public SkylarkPath path(Object path) throws EvalException, InterruptedException {
     return getPath("path()", path);
   }
 
-  private SkylarkPath getPath(String method, Object path) throws EvalException {
+  private SkylarkPath getPath(String method, Object path)
+      throws EvalException, InterruptedException {
     if (path instanceof String) {
       PathFragment pathFragment = new PathFragment(path.toString());
       return new SkylarkPath(pathFragment.isAbsolute()
@@ -171,7 +172,8 @@
         "Create a symlink on the filesystem, the destination of the symlink should be in the "
             + "output directory. <code>from</code> can also be a label to a file."
   )
-  public void symlink(Object from, Object to) throws RepositoryFunctionException, EvalException {
+  public void symlink(Object from, Object to)
+      throws RepositoryFunctionException, EvalException, InterruptedException {
     SkylarkPath fromPath = getPath("symlink()", from);
     SkylarkPath toPath = getPath("symlink()", to);
     try {
@@ -198,26 +200,25 @@
   }
 
   @SkylarkCallable(name = "file", documented = false)
-  public void createFile(Object path) throws RepositoryFunctionException, EvalException {
+  public void createFile(Object path)
+      throws RepositoryFunctionException, EvalException, InterruptedException {
     createFile(path, "");
   }
 
-  @SkylarkCallable(
-      name = "file",
-      documented = false
-  )
+  @SkylarkCallable(name = "file", documented = false)
   public void createFile(Object path, String content)
-      throws RepositoryFunctionException, EvalException {
+      throws RepositoryFunctionException, EvalException, InterruptedException {
     createFile(path, content, true);
   }
 
   @SkylarkCallable(
     name = "file",
-    doc = "Generate a file in the output directory with the provided content. An optional third "
-        + "argument set the executable bit to on or off (default to True)."
+    doc =
+        "Generate a file in the output directory with the provided content. An optional third "
+            + "argument set the executable bit to on or off (default to True)."
   )
   public void createFile(Object path, String content, Boolean executable)
-      throws RepositoryFunctionException, EvalException {
+      throws RepositoryFunctionException, EvalException, InterruptedException {
     SkylarkPath p = getPath("file()", path);
     try {
       checkInOutputDirectory(p);
@@ -233,28 +234,25 @@
     }
   }
 
-  @SkylarkCallable(
-      name = "template",
-      documented = false
-  )
+  @SkylarkCallable(name = "template", documented = false)
   public void createFileFromTemplate(
       Object path, Object template, Map<String, String> substitutions)
-      throws RepositoryFunctionException, EvalException {
+      throws RepositoryFunctionException, EvalException, InterruptedException {
     createFileFromTemplate(path, template, substitutions, true);
   }
 
   @SkylarkCallable(
-      name = "template",
-      doc =
-          "Generate a new file using a <code>template</code>. Every occurrence in "
-              + "<code>template</code> of a key of <code>substitutions</code> will be replaced by "
-              + "the corresponding value. The result is written in <code>path</code>. An optional"
-              + "<code>executable</code> argument (default to true) can be set to turn on or off"
-              + "the executable bit."
+    name = "template",
+    doc =
+        "Generate a new file using a <code>template</code>. Every occurrence in "
+            + "<code>template</code> of a key of <code>substitutions</code> will be replaced by "
+            + "the corresponding value. The result is written in <code>path</code>. An optional"
+            + "<code>executable</code> argument (default to true) can be set to turn on or off"
+            + "the executable bit."
   )
   public void createFileFromTemplate(
-        Object path, Object template, Map<String, String> substitutions, Boolean executable)
-    throws RepositoryFunctionException, EvalException {
+      Object path, Object template, Map<String, String> substitutions, Boolean executable)
+      throws RepositoryFunctionException, EvalException, InterruptedException {
     SkylarkPath p = getPath("template()", path);
     SkylarkPath t = getPath("template()", template);
     try {
@@ -522,7 +520,7 @@
   }
 
   // Resolve the label given by value into a file path.
-  private SkylarkPath getPathFromLabel(Label label) throws EvalException {
+  private SkylarkPath getPathFromLabel(Label label) throws EvalException, InterruptedException {
     // Look for package.
     if (label.getPackageIdentifier().getRepository().isDefault()) {
       try {
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java
index 4db1a92..0bc74f4 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java
@@ -35,11 +35,9 @@
 import com.google.devtools.build.lib.packages.Attribute.SplitTransition;
 import com.google.devtools.build.lib.packages.Attribute.Transition;
 import com.google.devtools.build.lib.rules.cpp.CppRuleClasses.LipoTransition;
-
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -53,7 +51,8 @@
       Cache<String, BuildConfiguration> cache,
       PackageProviderForConfigurations packageProvider,
       BuildOptions buildOptions,
-      EventHandler eventHandler) throws InvalidConfigurationException {
+      EventHandler eventHandler)
+      throws InvalidConfigurationException, InterruptedException {
     // Target configuration
     BuildConfiguration targetConfiguration = configurationFactory.getConfiguration(
         packageProvider, buildOptions, false, cache);
@@ -114,29 +113,28 @@
   }
 
   /**
-   * Gets the correct host configuration for this build. The behavior
-   * depends on the value of the --distinct_host_configuration flag.
+   * Gets the correct host configuration for this build. The behavior depends on the value of the
+   * --distinct_host_configuration flag.
    *
-   * <p>With --distinct_host_configuration=false, we use identical configurations
-   * for the host and target, and you can ignore everything below.  But please
-   * note: if you're cross-compiling for k8 on a piii machine, your build will
-   * fail.  This is a stopgap measure.
+   * <p>With --distinct_host_configuration=false, we use identical configurations for the host and
+   * target, and you can ignore everything below. But please note: if you're cross-compiling for k8
+   * on a piii machine, your build will fail. This is a stopgap measure.
    *
-   * <p>Currently, every build is (in effect) a cross-compile, in the strict
-   * sense that host and target configurations are unequal, thus we do not
-   * issue a "cross-compiling" warning.  (Perhaps we should?)
-   *   *
-   * @param requestConfig the requested target (not host!) configuration for
-   *   this build.
+   * <p>Currently, every build is (in effect) a cross-compile, in the strict sense that host and
+   * target configurations are unequal, thus we do not issue a "cross-compiling" warning. (Perhaps
+   * we should?) *
+   *
+   * @param requestConfig the requested target (not host!) configuration for this build.
    * @param buildOptions the configuration options used for the target configuration
    */
   @Nullable
-  private BuildConfiguration getHostConfigurationFromRequest(
+  private static BuildConfiguration getHostConfigurationFromRequest(
       ConfigurationFactory configurationFactory,
       PackageProviderForConfigurations loadedPackageProvider,
-      BuildConfiguration requestConfig, BuildOptions buildOptions,
+      BuildConfiguration requestConfig,
+      BuildOptions buildOptions,
       Cache<String, BuildConfiguration> cache)
-      throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     BuildConfiguration.Options commonOptions = buildOptions.get(BuildConfiguration.Options.class);
     if (!commonOptions.useDistinctHostConfiguration) {
       return requestConfig;
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java
index b30dae6..f26bfc9 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java
@@ -44,11 +44,9 @@
 import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease;
 import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.ToolPath;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
-import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -80,7 +78,7 @@
   @Override
   public SkyValue fetch(
       Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env)
-          throws SkyFunctionException {
+      throws InterruptedException, RepositoryFunctionException {
     prepareLocalRepositorySymlinkTree(rule, outputDirectory);
     PathFragment pathFragment = getTargetPath(rule, directories.getWorkspace());
     Path ndkSymlinkTreeDirectory = outputDirectory.getRelative("ndk");
@@ -267,7 +265,7 @@
   }
 
   private static NdkRelease getNdkRelease(Path directory, Environment env)
-      throws RepositoryFunctionException {
+      throws RepositoryFunctionException, InterruptedException {
 
     // For NDK r11+
     Path releaseFilePath = directory.getRelative("ndk/source.properties");
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java
index 7285c05..5852a19 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java
@@ -33,7 +33,6 @@
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.io.IOException;
 import java.util.Properties;
 
@@ -49,7 +48,7 @@
   @Override
   public SkyValue fetch(
       Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env)
-          throws SkyFunctionException {
+      throws SkyFunctionException, InterruptedException {
 
     prepareLocalRepositorySymlinkTree(rule, outputDirectory);
     PathFragment pathFragment = getTargetPath(rule, directories.getWorkspace());
@@ -111,7 +110,7 @@
 
   private static Properties getBuildToolsSourceProperties(
       Path directory, String buildToolsDirectory, Environment env)
-          throws RepositoryFunctionException {
+      throws RepositoryFunctionException, InterruptedException {
 
     Path sourcePropertiesFilePath = directory.getRelative(
         "build-tools/" + buildToolsDirectory + "/source.properties");
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java
index 418130b..479bfce 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java
@@ -42,7 +42,6 @@
 import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.List;
 import java.util.Map;
 
@@ -62,7 +61,8 @@
   }
 
   @Override
-  public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException {
+  public ConfiguredTarget create(RuleContext ruleContext)
+      throws RuleErrorException, InterruptedException {
     final List<Artifact> resolvedSrcs = Lists.newArrayList();
 
     final NestedSet<Artifact> filesToBuild =
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPatternResolver.java b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPatternResolver.java
index 8dc0f0a..a3aea66 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPatternResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPatternResolver.java
@@ -95,7 +95,7 @@
    * Returns true, if and only if the given package identifier corresponds to a package, i.e., a
    * file with the name {@code packageName/BUILD} exists in the appropriat repository.
    */
-  boolean isPackage(PackageIdentifier packageIdentifier);
+  boolean isPackage(PackageIdentifier packageIdentifier) throws InterruptedException;
 
   /**
    * Returns the target kind of the given target, for example {@code cc_library rule}.
diff --git a/src/main/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitor.java b/src/main/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitor.java
index baab884..01cdca1 100644
--- a/src/main/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitor.java
+++ b/src/main/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitor.java
@@ -20,7 +20,6 @@
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.google.devtools.build.lib.concurrent.ErrorClassifier.ErrorClassification;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.RejectedExecutionException;
@@ -29,7 +28,6 @@
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-
 import javax.annotation.Nullable;
 
 /** A {@link QuiescingExecutor} implementation that wraps an {@link ExecutorService}. */
@@ -143,7 +141,6 @@
   private final boolean ownExecutorService;
 
   private final ErrorClassifier errorClassifier;
-  private final ErrorHandler errorHandler;
 
   private static final Logger LOG = Logger.getLogger(AbstractQueueVisitor.class.getName());
 
@@ -176,25 +173,23 @@
         failFastOnException,
         poolName,
         EXECUTOR_FACTORY,
-        ErrorClassifier.DEFAULT,
-        ErrorHandler.NullHandler.INSTANCE);
+        ErrorClassifier.DEFAULT);
   }
 
   /**
    * Create the {@link AbstractQueueVisitor}.
    *
    * @param concurrent {@code true} if concurrency should be enabled. Only set to {@code false} for
-   *                   debugging.
+   *     debugging.
    * @param parallelism a measure of parallelism for the {@link ExecutorService}, such as {@code
-   *                    parallelism} in {@link java.util.concurrent.ForkJoinPool}, or both {@code
-   *                    corePoolSize} and {@code maximumPoolSize} in {@link ThreadPoolExecutor}.
+   *     parallelism} in {@link java.util.concurrent.ForkJoinPool}, or both {@code corePoolSize} and
+   *     {@code maximumPoolSize} in {@link ThreadPoolExecutor}.
    * @param keepAliveTime the keep-alive time for the {@link ExecutorService}, if applicable.
    * @param units the time units of keepAliveTime.
    * @param failFastOnException if {@code true}, don't run new actions after an uncaught exception.
    * @param poolName sets the name of threads spawned by the {@link ExecutorService}. If {@code
-   *                 null}, default thread naming will be used.
+   *     null}, default thread naming will be used.
    * @param errorClassifier an error classifier used to determine whether to log and/or stop jobs.
-   * @param errorHandler a handler for classified errors.
    */
   public AbstractQueueVisitor(
       boolean concurrent,
@@ -203,8 +198,7 @@
       TimeUnit units,
       boolean failFastOnException,
       String poolName,
-      ErrorClassifier errorClassifier,
-      ErrorHandler errorHandler) {
+      ErrorClassifier errorClassifier) {
     this(
         concurrent,
         parallelism,
@@ -213,27 +207,25 @@
         failFastOnException,
         poolName,
         EXECUTOR_FACTORY,
-        errorClassifier,
-        errorHandler);
+        errorClassifier);
   }
 
   /**
    * Create the {@link AbstractQueueVisitor}.
    *
    * @param concurrent {@code true} if concurrency should be enabled. Only set to {@code false} for
-   *                   debugging.
+   *     debugging.
    * @param parallelism a measure of parallelism for the {@link ExecutorService}, such as {@code
-   *                    parallelism} in {@link java.util.concurrent.ForkJoinPool}, or both {@code
-   *                    corePoolSize} and {@code maximumPoolSize} in {@link ThreadPoolExecutor}.
+   *     parallelism} in {@link java.util.concurrent.ForkJoinPool}, or both {@code corePoolSize} and
+   *     {@code maximumPoolSize} in {@link ThreadPoolExecutor}.
    * @param keepAliveTime the keep-alive time for the {@link ExecutorService}, if applicable.
    * @param units the time units of keepAliveTime.
    * @param failFastOnException if {@code true}, don't run new actions after an uncaught exception.
    * @param poolName sets the name of threads spawned by the {@link ExecutorService}. If {@code
-   *                 null}, default thread naming will be used.
+   *     null}, default thread naming will be used.
    * @param executorFactory the factory for constructing the executor service if {@code concurrent}
-   *                        is {@code true}.
+   *     is {@code true}.
    * @param errorClassifier an error classifier used to determine whether to log and/or stop jobs.
-   * @param errorHandler a handler for classified errors.
    */
   public AbstractQueueVisitor(
       boolean concurrent,
@@ -243,8 +235,7 @@
       boolean failFastOnException,
       String poolName,
       Function<ExecutorParams, ? extends ExecutorService> executorFactory,
-      ErrorClassifier errorClassifier,
-      ErrorHandler errorHandler) {
+      ErrorClassifier errorClassifier) {
     Preconditions.checkNotNull(poolName);
     Preconditions.checkNotNull(executorFactory);
     Preconditions.checkNotNull(errorClassifier);
@@ -258,7 +249,6 @@
                     parallelism, keepAliveTime, units, poolName, new BlockingStack<Runnable>()))
             : null;
     this.errorClassifier = errorClassifier;
-    this.errorHandler = errorHandler;
   }
 
   /**
@@ -278,8 +268,7 @@
         executorService,
         shutdownOnCompletion,
         failFastOnException,
-        ErrorClassifier.DEFAULT,
-        ErrorHandler.NullHandler.INSTANCE);
+        ErrorClassifier.DEFAULT);
   }
 
   /**
@@ -305,37 +294,32 @@
     this.ownExecutorService = shutdownOnCompletion;
     this.executorService = executorService;
     this.errorClassifier = ErrorClassifier.DEFAULT;
-    this.errorHandler = ErrorHandler.NullHandler.INSTANCE;
   }
 
   /**
    * Create the AbstractQueueVisitor.
    *
    * @param concurrent if {@code false}, run tasks inline instead of using the {@link
-   *                   ExecutorService}.
+   *     ExecutorService}.
    * @param executorService The {@link ExecutorService} to use.
    * @param shutdownOnCompletion If {@code true}, pass ownership of the {@link ExecutorService} to
-   *                             this class. The service will be shut down after a
-   *                             call to {@link #awaitQuiescence}. Callers must not shut down the
-   *                             {@link ExecutorService} while queue visitors use it.
+   *     this class. The service will be shut down after a call to {@link #awaitQuiescence}. Callers
+   *     must not shut down the {@link ExecutorService} while queue visitors use it.
    * @param failFastOnException if {@code true}, don't run new actions after an uncaught exception.
    * @param errorClassifier an error classifier used to determine whether to log and/or stop jobs.
-   * @param errorHandler a handler for classified errors.
    */
   public AbstractQueueVisitor(
       boolean concurrent,
       ExecutorService executorService,
       boolean shutdownOnCompletion,
       boolean failFastOnException,
-      ErrorClassifier errorClassifier,
-      ErrorHandler errorHandler) {
+      ErrorClassifier errorClassifier) {
     Preconditions.checkArgument(executorService != null || !concurrent);
     this.concurrent = concurrent;
     this.failFastOnException = failFastOnException;
     this.ownExecutorService = shutdownOnCompletion;
     this.executorService = executorService;
     this.errorClassifier = errorClassifier;
-    this.errorHandler = errorHandler;
   }
 
   /**
@@ -358,8 +342,7 @@
         false,
         poolName,
         EXECUTOR_FACTORY,
-        ErrorClassifier.DEFAULT,
-        ErrorHandler.NullHandler.INSTANCE);
+        ErrorClassifier.DEFAULT);
   }
 
 
@@ -437,7 +420,6 @@
         default:
           break;
     }
-    errorHandler.handle(e, errorClassification);
     if (unhandled == null
         || errorClassification.compareTo(errorClassifier.classify(unhandled)) > 0) {
       // Save the most severe error.
diff --git a/src/main/java/com/google/devtools/build/lib/concurrent/ForkJoinQuiescingExecutor.java b/src/main/java/com/google/devtools/build/lib/concurrent/ForkJoinQuiescingExecutor.java
index 54bb572..45132a1 100644
--- a/src/main/java/com/google/devtools/build/lib/concurrent/ForkJoinQuiescingExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/concurrent/ForkJoinQuiescingExecutor.java
@@ -23,15 +23,13 @@
 // maintaining AQV.remainingTasks.
 public class ForkJoinQuiescingExecutor extends AbstractQueueVisitor {
 
-  public ForkJoinQuiescingExecutor(ForkJoinPool forkJoinPool, ErrorClassifier errorClassifier,
-      ErrorHandler errorHandler) {
+  public ForkJoinQuiescingExecutor(ForkJoinPool forkJoinPool, ErrorClassifier errorClassifier) {
     super(
         /*concurrent=*/ true,
         forkJoinPool,
         /*shutdownOnCompletion=*/ true,
         /*failFastOnException=*/ true,
-        errorClassifier,
-        errorHandler);
+        errorClassifier);
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java
index f37613f..d89e278 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java
@@ -136,7 +136,7 @@
   }
 
   @Override
-  public void visitLabels(AcceptsLabelAttribute observer) {
+  public void visitLabels(AcceptsLabelAttribute observer) throws InterruptedException {
     for (Attribute attribute : ruleClass.getAttributes()) {
       Type<?> type = attribute.getType();
       // TODO(bazel-team): clean up the typing / visitation interface so we don't have to
@@ -148,10 +148,9 @@
     }
   }
 
-  /**
-   * Visits all labels reachable from the given attribute.
-   */
-  protected void visitLabels(Attribute attribute, AcceptsLabelAttribute observer) {
+  /** Visits all labels reachable from the given attribute. */
+  protected void visitLabels(Attribute attribute, AcceptsLabelAttribute observer)
+      throws InterruptedException {
     Type<?> type = attribute.getType();
     Object value = get(attribute.getName(), type);
     if (value != null) { // null values are particularly possible for computed defaults.
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java
index 454cd71..4fab639 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java
@@ -86,8 +86,7 @@
   }
 
   /**
-   * Override that also visits the rule's configurable attribute keys (which are
-   * themselves labels).
+   * Override that also visits the rule's configurable attribute keys (which are themselves labels).
    *
    * <p>Note that we directly parse the selectors rather than just calling {@link #visitAttribute}
    * to iterate over all possible values. That's because {@link #visitAttribute} can grow
@@ -96,12 +95,14 @@
    * path whenever actual value iteration isn't specifically needed.
    */
   @Override
-  protected void visitLabels(Attribute attribute, AcceptsLabelAttribute observer) {
+  protected void visitLabels(Attribute attribute, AcceptsLabelAttribute observer)
+      throws InterruptedException {
     visitLabels(attribute, true, observer);
   }
 
-  private void visitLabels(Attribute attribute, boolean includeSelectKeys,
-    AcceptsLabelAttribute observer) {
+  private void visitLabels(
+      Attribute attribute, boolean includeSelectKeys, AcceptsLabelAttribute observer)
+      throws InterruptedException {
     Type<?> type = attribute.getType();
     SelectorList<?> selectorList = getSelectorList(attribute.getName(), type);
     if (selectorList == null) {
@@ -137,12 +138,13 @@
   }
 
   /**
-   * Returns all labels reachable via the given attribute. If a label is listed multiple times,
-   * each instance appears in the returned list.
+   * Returns all labels reachable via the given attribute. If a label is listed multiple times, each
+   * instance appears in the returned list.
    *
    * @param includeSelectKeys whether to include config_setting keys for configurable attributes
    */
-  public List<Label> getReachableLabels(String attributeName, boolean includeSelectKeys) {
+  public List<Label> getReachableLabels(String attributeName, boolean includeSelectKeys)
+      throws InterruptedException {
     final ImmutableList.Builder<Label> builder = ImmutableList.builder();
     visitLabels(getAttributeDefinition(attributeName), includeSelectKeys,
         new AcceptsLabelAttribute() {
@@ -520,8 +522,10 @@
           return owner.get(attributeName, type);
         }
         if (!directMap.containsKey(attributeName)) {
-          throw new IllegalArgumentException("attribute \"" + attributeName
-              + "\" isn't available in this computed default context");
+          throw new IllegalArgumentException(
+              "attribute \""
+                  + attributeName
+                  + "\" isn't available in this computed default context");
         }
         return type.cast(directMap.get(attributeName));
       }
@@ -531,34 +535,70 @@
         return owner.isConfigurable(attributeName, type);
       }
 
-      @Override public String getName() { return owner.getName(); }
-      @Override public Label getLabel() { return owner.getLabel(); }
-      @Override public Iterable<String> getAttributeNames() {
-        return ImmutableList.<String>builder()
-            .addAll(directMap.keySet()).addAll(nonConfigurableAttributes).build();
+      @Override
+      public String getName() {
+        return owner.getName();
       }
+
       @Override
-      public void visitLabels(AcceptsLabelAttribute observer) { owner.visitLabels(observer); }
+      public Label getLabel() {
+        return owner.getLabel();
+      }
+
       @Override
-      public String getPackageDefaultHdrsCheck() { return owner.getPackageDefaultHdrsCheck(); }
+      public Iterable<String> getAttributeNames() {
+        return ImmutableList.<String>builder()
+            .addAll(directMap.keySet())
+            .addAll(nonConfigurableAttributes)
+            .build();
+      }
+
       @Override
-      public Boolean getPackageDefaultTestOnly() { return owner.getPackageDefaultTestOnly(); }
+      public void visitLabels(AcceptsLabelAttribute observer) throws InterruptedException {
+        owner.visitLabels(observer);
+      }
+
       @Override
-      public String getPackageDefaultDeprecation() { return owner.getPackageDefaultDeprecation(); }
+      public String getPackageDefaultHdrsCheck() {
+        return owner.getPackageDefaultHdrsCheck();
+      }
+
+      @Override
+      public Boolean getPackageDefaultTestOnly() {
+        return owner.getPackageDefaultTestOnly();
+      }
+
+      @Override
+      public String getPackageDefaultDeprecation() {
+        return owner.getPackageDefaultDeprecation();
+      }
+
       @Override
       public ImmutableList<String> getPackageDefaultCopts() {
         return owner.getPackageDefaultCopts();
       }
-      @Nullable @Override
-      public Type<?> getAttributeType(String attrName) { return owner.getAttributeType(attrName); }
-      @Nullable @Override  public Attribute getAttributeDefinition(String attrName) {
+
+      @Nullable
+      @Override
+      public Type<?> getAttributeType(String attrName) {
+        return owner.getAttributeType(attrName);
+      }
+
+      @Nullable
+      @Override
+      public Attribute getAttributeDefinition(String attrName) {
         return owner.getAttributeDefinition(attrName);
       }
-      @Override public boolean isAttributeValueExplicitlySpecified(String attributeName) {
+
+      @Override
+      public boolean isAttributeValueExplicitlySpecified(String attributeName) {
         return owner.isAttributeValueExplicitlySpecified(attributeName);
       }
+
       @Override
-      public boolean has(String attrName, Type<?> type) { return owner.has(attrName, type); }
+      public boolean has(String attrName, Type<?> type) {
+        return owner.has(attrName, type);
+      }
     };
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java b/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java
index b5c4508..3e62f29 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java
@@ -16,7 +16,6 @@
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.syntax.Type;
-
 import javax.annotation.Nullable;
 
 /**
@@ -91,19 +90,19 @@
     /**
      * Accept a (Label, Attribute) pair describing a dependency edge.
      *
-     * @param label the target node of the (Rule, Label) edge.
-     *     The source node should already be known.
+     * @param label the target node of the (Rule, Label) edge. The source node should already be
+     *     known.
      * @param attribute the attribute.
      */
-    void acceptLabelAttribute(Label label, Attribute attribute);
+    void acceptLabelAttribute(Label label, Attribute attribute) throws InterruptedException;
   }
 
   /**
-   * For all attributes that contain labels in their values (either by *being* a label or
-   * being a collection that includes labels), visits every label and notifies the
-   * specified observer at each visit.
+   * For all attributes that contain labels in their values (either by *being* a label or being a
+   * collection that includes labels), visits every label and notifies the specified observer at
+   * each visit.
    */
-  void visitLabels(AcceptsLabelAttribute observer);
+  void visitLabels(AcceptsLabelAttribute observer) throws InterruptedException;
 
   // TODO(bazel-team): These methods are here to support computed defaults that inherit
   // package-level default values. Instead, we should auto-inherit and remove the computed
diff --git a/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java
index 174b9b9..e57476c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java
@@ -17,7 +17,6 @@
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import javax.annotation.Nullable;
 
 /**
@@ -74,7 +73,7 @@
   }
 
   @Override
-  public void visitLabels(AcceptsLabelAttribute observer) {
+  public void visitLabels(AcceptsLabelAttribute observer) throws InterruptedException {
     delegate.visitLabels(observer);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java b/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java
index c6b0004..dd9678a 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java
@@ -24,7 +24,6 @@
 import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import java.util.Map;
 
 /**
@@ -69,7 +68,7 @@
     return rule;
   }
 
-  void addBindRule(
+  static void addBindRule(
       Builder pkg,
       RuleClass bindRuleClass,
       Label virtual,
@@ -102,7 +101,8 @@
     rule.setVisibility(ConstantRuleVisibility.PUBLIC);
   }
 
-  private void overwriteRule(Package.Builder pkg, Rule rule) throws Package.NameConflictException {
+  private static void overwriteRule(Package.Builder pkg, Rule rule)
+      throws Package.NameConflictException, InterruptedException {
     Preconditions.checkArgument(rule.getOutputFiles().isEmpty());
     Target old = pkg.targets.get(rule.getName());
     if (old != null) {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Globber.java b/src/main/java/com/google/devtools/build/lib/packages/Globber.java
index 64d6179..a2f980c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Globber.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Globber.java
@@ -29,14 +29,13 @@
   }
 
   /**
-   * Asynchronously starts the given glob computation and returns a token for fetching the
-   * result.
+   * Asynchronously starts the given glob computation and returns a token for fetching the result.
    *
    * @throws BadGlobException if any of the patterns in {@code includes} or {@code excludes} are
    *     invalid.
    */
   Token runAsync(List<String> includes, List<String> excludes, boolean excludeDirs)
-      throws BadGlobException;
+      throws BadGlobException, InterruptedException;
 
   /**
    * Fetches the result of a previously started glob computation. The returned list must be ordered
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java
index 90e3b59..f1d9b51 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Package.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java
@@ -1265,12 +1265,12 @@
       }
     }
 
-    void addRule(Rule rule) throws NameConflictException {
+    void addRule(Rule rule) throws NameConflictException, InterruptedException {
       checkForConflicts(rule);
       addRuleUnchecked(rule);
     }
 
-    private Builder beforeBuild() {
+    private Builder beforeBuild() throws InterruptedException {
       Preconditions.checkNotNull(pkg);
       Preconditions.checkNotNull(filename);
       Preconditions.checkNotNull(buildFileLabel);
@@ -1323,7 +1323,7 @@
     }
 
     /** Intended for use by {@link com.google.devtools.build.lib.skyframe.PackageFunction} only. */
-    public Builder buildPartial() {
+    public Builder buildPartial() throws InterruptedException {
       if (alreadyBuilt) {
         return this;
       }
@@ -1371,7 +1371,7 @@
       return externalPackageData;
     }
 
-    public Package build() {
+    public Package build() throws InterruptedException {
       if (alreadyBuilt) {
         return pkg;
       }
@@ -1399,14 +1399,15 @@
     }
 
     /**
-     * Precondition check for addRule.  We must maintain these invariants of the
-     * package:
-     * - Each name refers to at most one target.
-     * - No rule with errors is inserted into the package.
-     * - The generating rule of every output file in the package must itself be
-     *   in the package.
+     * Precondition check for addRule. We must maintain these invariants of the package:
+     *
+     * <ul>
+     * <li>Each name refers to at most one target.
+     * <li>No rule with errors is inserted into the package.
+     * <li>The generating rule of every output file in the package must itself be in the package.
+     * </ul>
      */
-    private void checkForConflicts(Rule rule) throws NameConflictException {
+    private void checkForConflicts(Rule rule) throws NameConflictException, InterruptedException {
       String name = rule.getName();
       Target existing = targets.get(name);
       if (existing != null) {
@@ -1451,17 +1452,15 @@
     }
 
     /**
-     * A utility method that checks for conflicts between
-     * input file names and output file names for a rule from a build
-     * file.
-     * @param rule the rule whose inputs and outputs are
-     *       to be checked for conflicts.
-     * @param outputFiles a set containing the names of output
-     *       files to be generated by the rule.
+     * A utility method that checks for conflicts between input file names and output file names for
+     * a rule from a build file.
+     *
+     * @param rule the rule whose inputs and outputs are to be checked for conflicts.
+     * @param outputFiles a set containing the names of output files to be generated by the rule.
      * @throws NameConflictException if a conflict is found.
      */
     private void checkForInputOutputConflicts(Rule rule, Set<String> outputFiles)
-        throws NameConflictException {
+        throws NameConflictException, InterruptedException {
       PathFragment packageFragment = rule.getLabel().getPackageFragment();
       for (Label inputLabel : rule.getLabels()) {
         if (packageFragment.equals(inputLabel.getPackageFragment())
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Rule.java b/src/main/java/com/google/devtools/build/lib/packages/Rule.java
index dd5df33..29af9a5 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Rule.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Rule.java
@@ -398,10 +398,8 @@
     return false;
   }
 
-  /**
-   * Returns a new List instance containing all direct dependencies (all types).
-   */
-  public Collection<Label> getLabels() {
+  /** Returns a new List instance containing all direct dependencies (all types). */
+  public Collection<Label> getLabels() throws InterruptedException {
     final List<Label> labels = Lists.newArrayList();
     AggregatingAttributeMapper.of(this).visitLabels(new AttributeMap.AcceptsLabelAttribute() {
       @Override
@@ -413,29 +411,30 @@
   }
 
   /**
-   * Returns a new Collection containing all Labels that match a given Predicate,
-   * not including outputs.
+   * Returns a new Collection containing all Labels that match a given Predicate, not including
+   * outputs.
    *
-   * @param predicate A binary predicate that determines if a label should be
-   *     included in the result. The predicate is evaluated with this rule and
-   *     the attribute that contains the label. The label will be contained in the
-   *     result iff (the predicate returned {@code true} and the labels are not outputs)
+   * @param predicate A binary predicate that determines if a label should be included in the
+   *     result. The predicate is evaluated with this rule and the attribute that contains the
+   *     label. The label will be contained in the result iff (the predicate returned {@code true}
+   *     and the labels are not outputs)
    */
-  public Collection<Label> getLabels(BinaryPredicate<? super Rule, Attribute> predicate) {
+  public Collection<Label> getLabels(BinaryPredicate<? super Rule, Attribute> predicate)
+      throws InterruptedException {
     return ImmutableSortedSet.copyOf(getTransitions(predicate).values());
   }
 
   /**
-   * Returns a new Multimap containing all attributes that match a given Predicate and
-   * corresponding labels, not including outputs.
+   * Returns a new Multimap containing all attributes that match a given Predicate and corresponding
+   * labels, not including outputs.
    *
-   * @param predicate A binary predicate that determines if a label should be
-   *     included in the result. The predicate is evaluated with this rule and
-   *     the attribute that contains the label. The label will be contained in the
-   *     result iff (the predicate returned {@code true} and the labels are not outputs)
+   * @param predicate A binary predicate that determines if a label should be included in the
+   *     result. The predicate is evaluated with this rule and the attribute that contains the
+   *     label. The label will be contained in the result iff (the predicate returned {@code true}
+   *     and the labels are not outputs)
    */
   public Multimap<Attribute, Label> getTransitions(
-      final BinaryPredicate<? super Rule, Attribute> predicate) {
+      final BinaryPredicate<? super Rule, Attribute> predicate) throws InterruptedException {
     final Multimap<Attribute, Label> transitions = HashMultimap.create();
     // TODO(bazel-team): move this to AttributeMap, too. Just like visitLabels, which labels should
     // be visited may depend on the calling context. We shouldn't implicitly decide this for
@@ -651,7 +650,7 @@
   // null-valued, with a packageFragment that is null...). The bug that prompted
   // the introduction of this code is #2210848 (NullPointerException in
   // Package.checkForConflicts() ).
-  void checkForNullLabels() {
+  void checkForNullLabels() throws InterruptedException {
     AggregatingAttributeMapper.of(this).visitLabels(
         new AttributeMap.AcceptsLabelAttribute() {
           @Override
diff --git a/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java b/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java
index 8a90c10..85dc320 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java
@@ -18,10 +18,8 @@
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.syntax.Type;
-
 import java.util.HashMap;
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -185,7 +183,7 @@
     return index != -1 ? ruleClass.substring(0, index) : ruleClass;
   }
 
-  private static boolean isExplicitDependency(Rule rule, Label label) {
+  private static boolean isExplicitDependency(Rule rule, Label label) throws InterruptedException {
     if (rule.getVisibility().getDependencyLabels().contains(label)) {
       return true;
     }
@@ -227,11 +225,11 @@
   }
 
   /**
-   * Return nicely formatted error message that {@link Label} label that was pointed to by
-   * {@link Target} target did not exist, due to {@link NoSuchThingException} e.
+   * Return nicely formatted error message that {@link Label} label that was pointed to by {@link
+   * Target} target did not exist, due to {@link NoSuchThingException} e.
    */
-  public static String formatMissingEdge(@Nullable Target target, Label label,
-      NoSuchThingException e) {
+  public static String formatMissingEdge(
+      @Nullable Target target, Label label, NoSuchThingException e) throws InterruptedException {
     // instanceof returns false if target is null (which is exploited here)
     if (target instanceof Rule) {
       Rule rule = (Rule) target;
diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/PackageProvider.java b/src/main/java/com/google/devtools/build/lib/pkgcache/PackageProvider.java
index b99d797..23464b4 100644
--- a/src/main/java/com/google/devtools/build/lib/pkgcache/PackageProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/pkgcache/PackageProvider.java
@@ -47,17 +47,19 @@
   /**
    * Returns whether a package with the given name exists. That is, returns whether all the
    * following hold
+   *
    * <ol>
-   *   <li>{@code packageName} is a valid package name</li>
-   *   <li>there is a BUILD file for the package</li>
-   *   <li>the package is not considered deleted via --deleted_packages</li>
+   * <li>{@code packageName} is a valid package name
+   * <li>there is a BUILD file for the package
+   * <li>the package is not considered deleted via --deleted_packages
    * </ol>
    *
-   * <p> If these don't hold, then attempting to read the package with {@link #getPackage} may fail
+   * <p>If these don't hold, then attempting to read the package with {@link #getPackage} may fail
    * or may return a package containing errors.
    *
    * @param eventHandler the eventHandler on which to report warnings and errors
    * @param packageName the name of the package.
    */
-  boolean isPackage(EventHandler eventHandler, PackageIdentifier packageName);
+  boolean isPackage(EventHandler eventHandler, PackageIdentifier packageName)
+      throws InterruptedException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java
index 37c81b0..bdf3baa 100644
--- a/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java
@@ -21,7 +21,6 @@
 import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.lib.vfs.RootedPath;
-
 import java.util.Map;
 
 /**
@@ -32,16 +31,18 @@
   /**
    * Returns the names of all the packages under a given directory.
    *
-   * <p>Packages returned by this method and passed into
-   * {@link #bulkGetPackages(EventHandler, Iterable)} are expected to return successful
-   * {@link Package} values.
+   * <p>Packages returned by this method and passed into {@link #bulkGetPackages(EventHandler,
+   * Iterable)} are expected to return successful {@link Package} values.
    *
    * @param directory a {@link RootedPath} specifying the directory to search
-   * @param excludedSubdirectories a set of {@link PathFragment}s, all of which are beneath
-   *     {@code directory}, specifying transitive subdirectories to exclude
+   * @param excludedSubdirectories a set of {@link PathFragment}s, all of which are beneath {@code
+   *     directory}, specifying transitive subdirectories to exclude
    */
-  Iterable<PathFragment> getPackagesUnderDirectory(RepositoryName repository,
-      PathFragment directory, ImmutableSet<PathFragment> excludedSubdirectories);
+  Iterable<PathFragment> getPackagesUnderDirectory(
+      RepositoryName repository,
+      PathFragment directory,
+      ImmutableSet<PathFragment> excludedSubdirectories)
+      throws InterruptedException;
 
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/TargetEdgeObserver.java b/src/main/java/com/google/devtools/build/lib/pkgcache/TargetEdgeObserver.java
index 294920a..9e30d92 100644
--- a/src/main/java/com/google/devtools/build/lib/pkgcache/TargetEdgeObserver.java
+++ b/src/main/java/com/google/devtools/build/lib/pkgcache/TargetEdgeObserver.java
@@ -18,7 +18,6 @@
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.NoSuchThingException;
 import com.google.devtools.build.lib.packages.Target;
-
 import javax.annotation.Nullable;
 
 /**
@@ -41,13 +40,13 @@
   /**
    * Called when a Target has a reference to a non-existent target.
    *
-   * @param target the target.  May be null (e.g. in the case of an implicit
-   *   dependency on a subincluded file).
-   * @param to a label reference in the rule, which does not correspond
-   *     to a valid target.
+   * @param target the target. May be null (e.g. in the case of an implicit dependency on a
+   *     subincluded file).
+   * @param to a label reference in the rule, which does not correspond to a valid target.
    * @param e the corresponding exception thrown
    */
-  void missingEdge(@Nullable Target target, Label to, NoSuchThingException e);
+  void missingEdge(@Nullable Target target, Label to, NoSuchThingException e)
+      throws InterruptedException;
 
   /**
    * Called when a node is discovered. May be called
diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/TargetPatternResolverUtil.java b/src/main/java/com/google/devtools/build/lib/pkgcache/TargetPatternResolverUtil.java
index d00db1e..d8534ca 100644
--- a/src/main/java/com/google/devtools/build/lib/pkgcache/TargetPatternResolverUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/pkgcache/TargetPatternResolverUtil.java
@@ -49,9 +49,9 @@
     return builder.build();
   }
 
-  public static void validatePatternPackage(String originalPattern,
-      PathFragment packageNameFragment, TargetPatternResolver<?> resolver)
-      throws TargetParsingException {
+  public static void validatePatternPackage(
+      String originalPattern, PathFragment packageNameFragment, TargetPatternResolver<?> resolver)
+      throws TargetParsingException, InterruptedException {
     String packageName = packageNameFragment.toString();
     // It's possible for this check to pass, but for
     // Label.validatePackageNameFull to report an error because the
diff --git a/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java
index 07df0c6..5df5599 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java
@@ -33,7 +33,6 @@
 import com.google.devtools.build.lib.query2.engine.QueryUtil.AggregateAllCallback;
 import com.google.devtools.build.lib.query2.engine.VariableContext;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -165,7 +164,8 @@
     }
   }
 
-  public abstract Target getTarget(Label label) throws TargetNotFoundException, QueryException;
+  public abstract Target getTarget(Label label)
+      throws TargetNotFoundException, QueryException, InterruptedException;
 
   protected boolean validateScope(Label label, boolean strict) throws QueryException {
     if (!labelFilter.apply(label)) {
@@ -181,7 +181,7 @@
   }
 
   public Set<T> evalTargetPattern(QueryExpression caller, String pattern)
-      throws QueryException {
+      throws QueryException, InterruptedException {
     try {
       preloadOrThrow(caller, ImmutableList.of(pattern));
     } catch (TargetParsingException e) {
diff --git a/src/main/java/com/google/devtools/build/lib/query2/BlazeQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/BlazeQueryEnvironment.java
index a29c2c6..ad6b540 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/BlazeQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/BlazeQueryEnvironment.java
@@ -48,7 +48,6 @@
 import com.google.devtools.build.lib.query2.engine.VariableContext;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -136,7 +135,8 @@
 
   @Override
   public void getTargetsMatchingPattern(
-      QueryExpression caller, String pattern, Callback<Target> callback) throws QueryException {
+      QueryExpression caller, String pattern, Callback<Target> callback)
+      throws QueryException, InterruptedException {
     // We can safely ignore the boolean error flag. The evaluateQuery() method above wraps the
     // entire query computation in an error sensor.
 
diff --git a/src/main/java/com/google/devtools/build/lib/query2/BlazeTargetAccessor.java b/src/main/java/com/google/devtools/build/lib/query2/BlazeTargetAccessor.java
index 81de429..d345a27 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/BlazeTargetAccessor.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/BlazeTargetAccessor.java
@@ -38,7 +38,6 @@
 import com.google.devtools.build.lib.query2.engine.QueryVisibility;
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
@@ -71,8 +70,9 @@
   }
 
   @Override
-  public List<Target> getLabelListAttr(QueryExpression caller, Target target, String attrName,
-      String errorMsgPrefix) throws QueryException {
+  public List<Target> getLabelListAttr(
+      QueryExpression caller, Target target, String attrName, String errorMsgPrefix)
+      throws QueryException, InterruptedException {
     Preconditions.checkArgument(target instanceof Rule);
 
     List<Target> result = new ArrayList<>();
@@ -163,7 +163,8 @@
   }
 
   @Override
-  public Set<QueryVisibility<Target>> getVisibility(Target target) throws QueryException {
+  public Set<QueryVisibility<Target>> getVisibility(Target target)
+      throws QueryException, InterruptedException {
     ImmutableSet.Builder<QueryVisibility<Target>> result = ImmutableSet.builder();
     result.add(QueryVisibility.samePackage(target, this));
     convertVisibility(result, target);
@@ -172,9 +173,8 @@
 
   // CAUTION: keep in sync with ConfiguredTargetFactory#convertVisibility()
   private void convertVisibility(
-      ImmutableSet.Builder<QueryVisibility<Target>> packageSpecifications,
-      Target target)
-      throws QueryException {
+      ImmutableSet.Builder<QueryVisibility<Target>> packageSpecifications, Target target)
+      throws QueryException, InterruptedException {
    RuleVisibility ruleVisibility = target.getVisibility();
    if (ruleVisibility instanceof ConstantRuleVisibility) {
      if (((ConstantRuleVisibility) ruleVisibility).isPubliclyVisible()) {
@@ -203,7 +203,7 @@
 
   private void convertGroupVisibility(
       PackageGroup group, ImmutableSet.Builder<QueryVisibility<Target>> packageSpecifications)
-      throws QueryException, TargetNotFoundException {
+      throws QueryException, TargetNotFoundException, InterruptedException {
     for (Label include : group.getIncludes()) {
       convertGroupVisibility((PackageGroup) queryEnvironment.getTarget(include),
           packageSpecifications);
diff --git a/src/main/java/com/google/devtools/build/lib/query2/ErrorPrintingTargetEdgeErrorObserver.java b/src/main/java/com/google/devtools/build/lib/query2/ErrorPrintingTargetEdgeErrorObserver.java
index b129d59..11b6f79 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/ErrorPrintingTargetEdgeErrorObserver.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/ErrorPrintingTargetEdgeErrorObserver.java
@@ -45,7 +45,8 @@
 
   @ThreadSafety.ThreadSafe
   @Override
-  public void missingEdge(Target target, Label label, NoSuchThingException e) {
+  public void missingEdge(Target target, Label label, NoSuchThingException e)
+      throws InterruptedException {
     eventHandler.handle(Event.error(TargetUtils.getLocationMaybe(target),
         TargetUtils.formatMissingEdge(target, label, e)));
     super.missingEdge(target, label, e);
diff --git a/src/main/java/com/google/devtools/build/lib/query2/LabelVisitor.java b/src/main/java/com/google/devtools/build/lib/query2/LabelVisitor.java
index 8409838..c023601 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/LabelVisitor.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/LabelVisitor.java
@@ -41,7 +41,6 @@
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.pkgcache.PackageProvider;
 import com.google.devtools.build.lib.pkgcache.TargetEdgeObserver;
-
 import java.util.Collection;
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
@@ -292,13 +291,12 @@
     }
 
     /**
-     * Visit the specified labels and follow the transitive closure of their
-     * outbound dependencies.
+     * Visit the specified labels and follow the transitive closure of their outbound dependencies.
      *
      * @param targets the targets to visit
      */
     @ThreadSafe
-    public void visitTargets(Iterable<Target> targets) {
+    public void visitTargets(Iterable<Target> targets) throws InterruptedException {
       for (Target target : targets) {
         visit(null, null, target, 0, 0);
       }
@@ -340,13 +338,15 @@
 
     private Runnable newVisitRunnable(final Target from, final Attribute attr, final Label label,
         final int depth, final int count) {
-      return new Runnable () {
+      return new Runnable() {
         @Override
         public void run() {
           try {
-            visit(from, attr, packageProvider.getTarget(eventHandler, label), depth + 1, count);
-          } catch (NoSuchThingException e) {
-            observeError(from, label, e);
+            try {
+              visit(from, attr, packageProvider.getTarget(eventHandler, label), depth + 1, count);
+            } catch (NoSuchThingException e) {
+              observeError(from, label, e);
+            }
           } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
           }
@@ -381,7 +381,8 @@
      * @param rule the rule to visit
      */
     @ThreadSafe
-    private void visitRule(final Rule rule, final int depth, final int count) {
+    private void visitRule(final Rule rule, final int depth, final int count)
+        throws InterruptedException {
       // Follow all labels defined by this rule:
       AggregatingAttributeMapper.of(rule).visitLabels(new AttributeMap.AcceptsLabelAttribute() {
         @Override
@@ -404,11 +405,11 @@
     /**
      * Visits the target and its package.
      *
-     * <p>Potentially blocking invocations into the package cache are
-     * enqueued in the worker pool if CONCURRENT.
+     * <p>Potentially blocking invocations into the package cache are enqueued in the worker pool if
+     * CONCURRENT.
      */
-    private void visit(
-        Target from, Attribute attribute, final Target target, int depth, int count) {
+    private void visit(Target from, Attribute attribute, final Target target, int depth, int count)
+        throws InterruptedException {
       if (target == null) {
         throw new NullPointerException(
             String.format("'%s' attribute '%s'",
@@ -439,12 +440,11 @@
     }
 
     /**
-     * Visit the specified target.
-     * Called in a worker thread if CONCURRENT.
+     * Visit the specified target. Called in a worker thread if CONCURRENT.
      *
      * @param target the target to visit
      */
-    private void visitTargetNode(Target target, int depth, int count) {
+    private void visitTargetNode(Target target, int depth, int count) throws InterruptedException {
       Integer minTargetDepth = visitedTargets.putIfAbsent(target.getLabel(), depth);
       if (minTargetDepth != null) {
         // The target was already visited at a greater depth.
@@ -493,7 +493,8 @@
       }
     }
 
-    private void observeError(Target from, Label label, NoSuchThingException e) {
+    private void observeError(Target from, Label label, NoSuchThingException e)
+        throws InterruptedException {
       for (TargetEdgeObserver observer : observers) {
         observer.missingEdge(from, label, e);
       }
diff --git a/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
index 40d8a89..2260282 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
@@ -18,8 +18,6 @@
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
@@ -82,6 +80,7 @@
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.lib.vfs.RootedPath;
 import com.google.devtools.build.skyframe.EvaluationResult;
+import com.google.devtools.build.skyframe.InterruptibleSupplier;
 import com.google.devtools.build.skyframe.SkyFunctionName;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
@@ -146,7 +145,7 @@
 
   // The following fields are set in the #beforeEvaluateQuery method.
   protected WalkableGraph graph;
-  private Supplier<ImmutableSet<PathFragment>> blacklistPatternsSupplier;
+  private InterruptibleSupplier<ImmutableSet<PathFragment>> blacklistPatternsSupplier;
   private RecursivePackageProviderBackedTargetPatternResolver resolver;
 
   public SkyQueryEnvironment(
@@ -186,7 +185,7 @@
     checkEvaluationResult(result, universeKey);
 
     graph = result.getWalkableGraph();
-    blacklistPatternsSupplier = Suppliers.memoize(new BlacklistSupplier(graph));
+    blacklistPatternsSupplier = InterruptibleSupplier.Memoize.of(new BlacklistSupplier(graph));
 
     ImmutableList<TargetPatternKey> universeTargetPatternKeys =
         PrepareDepsOfPatternsFunction.getTargetPatternKeys(
@@ -345,7 +344,8 @@
     return new QueryEvalResult(!eventHandler.hasErrors(), empty.get());
   }
 
-  private Map<Target, Collection<Target>> makeTargetsMap(Map<SkyKey, Iterable<SkyKey>> input) {
+  private Map<Target, Collection<Target>> makeTargetsMap(Map<SkyKey, Iterable<SkyKey>> input)
+      throws InterruptedException {
     ImmutableMap.Builder<Target, Collection<Target>> result = ImmutableMap.builder();
 
     Map<SkyKey, Target> allTargets =
@@ -365,15 +365,17 @@
     return result.build();
   }
 
-  private Map<Target, Collection<Target>> getRawFwdDeps(Iterable<Target> targets) {
+  private Map<Target, Collection<Target>> getRawFwdDeps(Iterable<Target> targets)
+      throws InterruptedException {
     return makeTargetsMap(graph.getDirectDeps(makeTransitiveTraversalKeys(targets)));
   }
 
-  private Map<Target, Collection<Target>> getRawReverseDeps(Iterable<Target> targets) {
+  private Map<Target, Collection<Target>> getRawReverseDeps(Iterable<Target> targets)
+      throws InterruptedException {
     return makeTargetsMap(graph.getReverseDeps(makeTransitiveTraversalKeys(targets)));
   }
 
-  private Set<Label> getAllowedDeps(Rule rule) {
+  private Set<Label> getAllowedDeps(Rule rule) throws InterruptedException {
     Set<Label> allowedLabels = new HashSet<>(rule.getTransitions(dependencyFilter).values());
     allowedLabels.addAll(rule.getVisibility().getDependencyLabels());
     // We should add deps from aspects, otherwise they are going to be filtered out.
@@ -381,7 +383,8 @@
     return allowedLabels;
   }
 
-  private Collection<Target> filterFwdDeps(Target target, Collection<Target> rawFwdDeps) {
+  private Collection<Target> filterFwdDeps(Target target, Collection<Target> rawFwdDeps)
+      throws InterruptedException {
     if (!(target instanceof Rule)) {
       return rawFwdDeps;
     }
@@ -405,7 +408,7 @@
   }
 
   @Override
-  public Collection<Target> getFwdDeps(Iterable<Target> targets) {
+  public Collection<Target> getFwdDeps(Iterable<Target> targets) throws InterruptedException {
     Set<Target> result = new HashSet<>();
     Map<Target, Collection<Target>> rawFwdDeps = getRawFwdDeps(targets);
     warnIfMissingTargets(targets, rawFwdDeps.keySet());
@@ -416,14 +419,15 @@
   }
 
   @Override
-  public Collection<Target> getReverseDeps(Iterable<Target> targets) {
+  public Collection<Target> getReverseDeps(Iterable<Target> targets) throws InterruptedException {
     Map<Target, Collection<Target>> rawReverseDeps = getRawReverseDeps(targets);
     warnIfMissingTargets(targets, rawReverseDeps.keySet());
 
     return processRawReverseDeps(rawReverseDeps);
   }
 
-  private Collection<Target> processRawReverseDeps(Map<Target, Collection<Target>> rawReverseDeps) {
+  private Collection<Target> processRawReverseDeps(Map<Target, Collection<Target>> rawReverseDeps)
+      throws InterruptedException {
     Set<Target> result = CompactHashSet.create();
     CompactHashSet<Target> visited =
         CompactHashSet.createWithExpectedSize(totalSizeOfCollections(rawReverseDeps.values()));
@@ -457,7 +461,7 @@
   }
 
   @Override
-  public Set<Target> getTransitiveClosure(Set<Target> targets) {
+  public Set<Target> getTransitiveClosure(Set<Target> targets) throws InterruptedException {
     Set<Target> visited = new HashSet<>();
     Collection<Target> current = targets;
     while (!current.isEmpty()) {
@@ -471,7 +475,7 @@
 
   // Implemented with a breadth-first search.
   @Override
-  public Set<Target> getNodesOnPath(Target from, Target to) {
+  public Set<Target> getNodesOnPath(Target from, Target to) throws InterruptedException {
     // Tree of nodes visited so far.
     Map<Target, Target> nodeToParent = new HashMap<>();
     // Contains all nodes left to visit in a (LIFO) stack.
@@ -595,7 +599,8 @@
   }
 
   @Override
-  public Target getTarget(Label label) throws TargetNotFoundException, QueryException {
+  public Target getTarget(Label label)
+      throws TargetNotFoundException, QueryException, InterruptedException {
     SkyKey packageKey = PackageValue.key(label.getPackageIdentifier());
     if (!graph.exists(packageKey)) {
       throw new QueryException(packageKey + " does not exist in graph");
@@ -617,7 +622,8 @@
     }
   }
 
-  public Map<PackageIdentifier, Package> bulkGetPackages(Iterable<PackageIdentifier> pkgIds) {
+  public Map<PackageIdentifier, Package> bulkGetPackages(Iterable<PackageIdentifier> pkgIds)
+      throws InterruptedException {
     Set<SkyKey> pkgKeys = ImmutableSet.copyOf(PackageValue.keys(pkgIds));
     ImmutableMap.Builder<PackageIdentifier, Package> pkgResults = ImmutableMap.builder();
     Map<SkyKey, SkyValue> packages = graph.getSuccessfulValues(pkgKeys);
@@ -631,7 +637,7 @@
 
   @Override
   public void buildTransitiveClosure(QueryExpression caller, Set<Target> targets, int maxDepth)
-      throws QueryException {
+      throws QueryException, InterruptedException {
     // Everything has already been loaded, so here we just check for errors so that we can
     // pre-emptively throw/report if needed.
     Iterable<SkyKey> transitiveTraversalKeys = makeTransitiveTraversalKeys(targets);
@@ -694,7 +700,8 @@
     }
   };
 
-  private Map<SkyKey, Target> makeTargetsFromSkyKeys(Iterable<SkyKey> keys) {
+  private Map<SkyKey, Target> makeTargetsFromSkyKeys(Iterable<SkyKey> keys)
+      throws InterruptedException {
     Multimap<SkyKey, SkyKey> packageKeyToTargetKeyMap = ArrayListMultimap.create();
     for (SkyKey key : keys) {
       Label label = SKYKEY_TO_LABEL.apply(key);
@@ -776,7 +783,8 @@
    *
    * <p>Note that there may not be nodes in the graph corresponding to the returned SkyKeys.
    */
-  private Collection<SkyKey> getSkyKeysForFileFragments(Iterable<PathFragment> pathFragments) {
+  private Collection<SkyKey> getSkyKeysForFileFragments(Iterable<PathFragment> pathFragments)
+      throws InterruptedException {
     Set<SkyKey> result = new HashSet<>();
     Multimap<PathFragment, PathFragment> currentToOriginal = ArrayListMultimap.create();
     for (PathFragment pathFragment : pathFragments) {
@@ -898,7 +906,8 @@
         .build();
   }
 
-  private static class BlacklistSupplier implements Supplier<ImmutableSet<PathFragment>> {
+  private static class BlacklistSupplier
+      implements InterruptibleSupplier<ImmutableSet<PathFragment>> {
     private final WalkableGraph graph;
 
     BlacklistSupplier(WalkableGraph graph) {
@@ -906,7 +915,7 @@
     }
 
     @Override
-    public ImmutableSet<PathFragment> get() {
+    public ImmutableSet<PathFragment> get() throws InterruptedException {
       return ((BlacklistedPackagePrefixesValue)
               graph.getValue(BlacklistedPackagePrefixesValue.key()))
           .getPatterns();
diff --git a/src/main/java/com/google/devtools/build/lib/query2/TargetEdgeErrorObserver.java b/src/main/java/com/google/devtools/build/lib/query2/TargetEdgeErrorObserver.java
index 3e81571..06c60ce 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/TargetEdgeErrorObserver.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/TargetEdgeErrorObserver.java
@@ -43,15 +43,16 @@
   private volatile boolean hasErrors = false;
 
   /**
-   * Reports an unresolved label error and records the fact that an error was
-   * encountered.
+   * Reports an unresolved label error and records the fact that an error was encountered.
+   *
    * @param target the target that referenced the unresolved label
    * @param label the label that could not be resolved
    * @param e the exception that was thrown when the label could not be resolved
    */
   @ThreadSafety.ThreadSafe
   @Override
-  public void missingEdge(Target target, Label label, NoSuchThingException e) {
+  public void missingEdge(Target target, Label label, NoSuchThingException e)
+      throws InterruptedException {
     hasErrors = true;
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java
index 88a2ea9..9653841 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java
@@ -14,11 +14,9 @@
 package com.google.devtools.build.lib.query2.engine;
 
 import com.google.common.collect.ImmutableList;
-
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
-
 import javax.annotation.Nonnull;
 
 /**
@@ -143,7 +141,7 @@
    * pattern, in 'blaze build' syntax.
    */
   void getTargetsMatchingPattern(QueryExpression owner, String pattern, Callback<T> callback)
-      throws QueryException;
+      throws QueryException, InterruptedException;
 
   /** Ensures the specified target exists. */
   // NOTE(bazel-team): this method is left here as scaffolding from a previous refactoring. It may
@@ -151,17 +149,16 @@
   T getOrCreate(T target);
 
   /** Returns the direct forward dependencies of the specified targets. */
-  Collection<T> getFwdDeps(Iterable<T> targets);
+  Collection<T> getFwdDeps(Iterable<T> targets) throws InterruptedException;
 
   /** Returns the direct reverse dependencies of the specified targets. */
-  Collection<T> getReverseDeps(Iterable<T> targets);
+  Collection<T> getReverseDeps(Iterable<T> targets) throws InterruptedException;
 
   /**
-   * Returns the forward transitive closure of all of the targets in
-   * "targets".  Callers must ensure that {@link #buildTransitiveClosure}
-   * has been called for the relevant subgraph.
+   * Returns the forward transitive closure of all of the targets in "targets". Callers must ensure
+   * that {@link #buildTransitiveClosure} has been called for the relevant subgraph.
    */
-  Set<T> getTransitiveClosure(Set<T> targets);
+  Set<T> getTransitiveClosure(Set<T> targets) throws InterruptedException;
 
   /**
    * Construct the dependency graph for a depth-bounded forward transitive closure
@@ -176,10 +173,8 @@
                               Set<T> targetNodes,
                               int maxDepth) throws QueryException, InterruptedException;
 
-  /**
-   * Returns the set of nodes on some path from "from" to "to".
-   */
-  Set<T> getNodesOnPath(T from, T to);
+  /** Returns the set of nodes on some path from "from" to "to". */
+  Set<T> getNodesOnPath(T from, T to) throws InterruptedException;
 
   /**
    * Eval an expression {@code expr} and pass the results to the {@code callback}.
@@ -201,12 +196,12 @@
   void reportBuildFileError(QueryExpression expression, String msg) throws QueryException;
 
   /**
-   * Returns the set of BUILD, and optionally sub-included and Skylark files that define the given set of
-   * targets. Each such file is itself represented as a target in the result.
+   * Returns the set of BUILD, and optionally sub-included and Skylark files that define the given
+   * set of targets. Each such file is itself represented as a target in the result.
    */
   Set<T> getBuildFiles(
       QueryExpression caller, Set<T> nodes, boolean buildFiles, boolean subincludes, boolean loads)
-      throws QueryException;
+      throws QueryException, InterruptedException;
 
   /**
    * Returns an object that can be used to query information about targets. Implementations should
@@ -307,8 +302,9 @@
      *
      * @throws IllegalArgumentException if target is not a rule (according to {@link #isRule})
      */
-    List<T> getLabelListAttr(QueryExpression caller, T target, String attrName,
-        String errorMsgPrefix) throws QueryException;
+    List<T> getLabelListAttr(
+        QueryExpression caller, T target, String attrName, String errorMsgPrefix)
+        throws QueryException, InterruptedException;
 
     /**
      * If the attribute of the given name on the given target is a string list, then this method
@@ -347,7 +343,7 @@
      * Returns the set of package specifications the given target is visible from, represented as
      * {@link QueryVisibility}s.
      */
-    Set<QueryVisibility<T>> getVisibility(T from) throws QueryException;
+    Set<QueryVisibility<T>> getVisibility(T from) throws QueryException, InterruptedException;
   }
 
   /** List of the default query functions. */
diff --git a/src/main/java/com/google/devtools/build/lib/query2/engine/TestsFunction.java b/src/main/java/com/google/devtools/build/lib/query2/engine/TestsFunction.java
index 02ce8cc..77dc6b4 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/engine/TestsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/engine/TestsFunction.java
@@ -19,7 +19,6 @@
 import com.google.devtools.build.lib.query2.engine.QueryEnvironment.ArgumentType;
 import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction;
 import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -161,12 +160,12 @@
     }
 
     /**
-     * Computes and returns the set of test rules in a particular suite.  Uses
-     * dynamic programming---a memoized version of {@link #computeTestsInSuite}.
+     * Computes and returns the set of test rules in a particular suite. Uses dynamic
+     * programming---a memoized version of {@link #computeTestsInSuite}.
      *
      * @precondition env.getAccessor().isTestSuite(testSuite)
      */
-    private Set<T> getTestsInSuite(T testSuite) throws QueryException {
+    private Set<T> getTestsInSuite(T testSuite) throws QueryException, InterruptedException {
       Set<T> tests = testsInSuite.get(testSuite);
       if (tests == null) {
         tests = Sets.newHashSet();
@@ -177,14 +176,15 @@
     }
 
     /**
-     * Populates 'result' with all the tests associated with the specified
-     * 'testSuite'.  Throws an exception if any target is missing.
+     * Populates 'result' with all the tests associated with the specified 'testSuite'. Throws an
+     * exception if any target is missing.
      *
-     * <p>CAUTION!  Keep this logic consistent with {@code TestsSuiteConfiguredTarget}!
+     * <p>CAUTION! Keep this logic consistent with {@code TestsSuiteConfiguredTarget}!
      *
      * @precondition env.getAccessor().isTestSuite(testSuite)
      */
-    private void computeTestsInSuite(T testSuite, Set<T> result) throws QueryException {
+    private void computeTestsInSuite(T testSuite, Set<T> result)
+        throws QueryException, InterruptedException {
       List<T> testsAndSuites = new ArrayList<>();
       // Note that testsAndSuites can contain input file targets; the test_suite rule does not
       // restrict the set of targets that can appear in tests or suites.
@@ -231,7 +231,8 @@
      *
      * @precondition env.getAccessor().isTestSuite(testSuite)
      */
-    private List<T> getPrerequisites(T testSuite, String attrName) throws QueryException {
+    private List<T> getPrerequisites(T testSuite, String attrName)
+        throws QueryException, InterruptedException {
       return env.getAccessor().getLabelListAttr(expression, testSuite, attrName,
           "couldn't expand '" + attrName
           + "' attribute of test_suite " + env.getAccessor().getLabel(testSuite) + ": ");
diff --git a/src/main/java/com/google/devtools/build/lib/query2/engine/VisibleFunction.java b/src/main/java/com/google/devtools/build/lib/query2/engine/VisibleFunction.java
index 03a2ccf..f69f134 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/engine/VisibleFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/engine/VisibleFunction.java
@@ -18,7 +18,6 @@
 import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Argument;
 import com.google.devtools.build.lib.query2.engine.QueryEnvironment.ArgumentType;
 import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction;
-
 import java.util.List;
 import java.util.Set;
 
@@ -71,11 +70,9 @@
     });
   }
 
-  /**
-   * Returns true if {@code target} is visible to all targets in {@code toSet}.
-   */
-  private static <T> boolean visibleToAll(
-      QueryEnvironment<T> env, Set<T> toSet, T target) throws QueryException {
+  /** Returns true if {@code target} is visible to all targets in {@code toSet}. */
+  private static <T> boolean visibleToAll(QueryEnvironment<T> env, Set<T> toSet, T target)
+      throws QueryException, InterruptedException {
     for (T to : toSet) {
       if (!visible(env, to, target)) {
         return false;
@@ -84,10 +81,9 @@
     return true;
   }
 
-  /**
-   * Returns true if the target {@code from} is visible to the target {@code to}.
-   */
-  public static <T> boolean visible(QueryEnvironment<T> env, T to, T from) throws QueryException {
+  /** Returns true if the target {@code from} is visible to the target {@code to}. */
+  public static <T> boolean visible(QueryEnvironment<T> env, T to, T from)
+      throws QueryException, InterruptedException {
     Set<QueryVisibility<T>> visiblePackages = env.getAccessor().getVisibility(from);
     for (QueryVisibility<T> spec : visiblePackages) {
       if (spec.contains(to)) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java
index 8afd384..5119a21 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java
@@ -653,17 +653,27 @@
     return attributesCollection.getExecutableRunfilesMap().get(executable);
   }
 
-  @SkylarkCallable(name = "info_file", structField = true, documented = false,
-      doc = "Returns the file that is used to hold the non-volatile workspace status for the "
-          + "current build request.")
-  public Artifact getStableWorkspaceStatus() {
+  @SkylarkCallable(
+    name = "info_file",
+    structField = true,
+    documented = false,
+    doc =
+        "Returns the file that is used to hold the non-volatile workspace status for the "
+            + "current build request."
+  )
+  public Artifact getStableWorkspaceStatus() throws InterruptedException {
     return ruleContext.getAnalysisEnvironment().getStableWorkspaceStatusArtifact();
   }
 
-  @SkylarkCallable(name = "version_file", structField = true, documented = false,
-      doc = "Returns the file that is used to hold the volatile workspace status for the "
-          + "current build request.")
-  public Artifact getVolatileWorkspaceStatus() {
+  @SkylarkCallable(
+    name = "version_file",
+    structField = true,
+    documented = false,
+    doc =
+        "Returns the file that is used to hold the volatile workspace status for the "
+            + "current build request."
+  )
+  public Artifact getVolatileWorkspaceStatus() throws InterruptedException {
     return ruleContext.getAnalysisEnvironment().getVolatileWorkspaceStatusArtifact();
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
index 97715cb68..42e9118 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
@@ -68,14 +68,12 @@
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -798,7 +796,8 @@
   }
 
   private static Artifact getStubDex(
-      RuleContext ruleContext, JavaSemantics javaSemantics, boolean split) {
+      RuleContext ruleContext, JavaSemantics javaSemantics, boolean split)
+      throws InterruptedException {
     String attribute =
         split ? "$incremental_split_stub_application" : "$incremental_stub_application";
 
@@ -868,8 +867,12 @@
 
   /** Generates an uncompressed _deploy.jar of all the runtime jars. */
   public static Artifact createDeployJar(
-      RuleContext ruleContext, JavaSemantics javaSemantics, AndroidCommon common,
-      JavaTargetAttributes attributes, Artifact deployJar) {
+      RuleContext ruleContext,
+      JavaSemantics javaSemantics,
+      AndroidCommon common,
+      JavaTargetAttributes attributes,
+      Artifact deployJar)
+      throws InterruptedException {
     new DeployArchiveBuilder(javaSemantics, ruleContext)
         .setOutputJar(deployJar)
         .setAttributes(attributes)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
index 278606d..4b9c950 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
@@ -38,7 +38,6 @@
 import com.google.devtools.common.options.EnumConverter;
 import com.google.devtools.common.options.Option;
 import com.google.devtools.common.options.OptionsParsingException;
-
 import java.util.List;
 import java.util.Set;
 
@@ -375,7 +374,7 @@
   public static class Loader implements ConfigurationFragmentFactory {
     @Override
     public Fragment create(ConfigurationEnvironment env, BuildOptions buildOptions)
-        throws InvalidConfigurationException {
+        throws InvalidConfigurationException, InterruptedException {
       AndroidConfiguration.Options androidOptions =
           buildOptions.get(AndroidConfiguration.Options.class);
       Label androidSdk = RedirectChaser.followRedirects(env, androidOptions.sdk, "android_sdk");
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
index 4e582aa..cbffcd8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
@@ -65,7 +65,8 @@
       String nativeDepsFileName,
       Multimap<String, TransitiveInfoCollection> depsByArchitecture,
       Map<String, CcToolchainProvider> toolchainMap,
-      Map<String, BuildConfiguration> configurationMap) {
+      Map<String, BuildConfiguration> configurationMap)
+      throws InterruptedException {
     Map<String, Iterable<Artifact>> result = new LinkedHashMap<>();
     for (Map.Entry<String, Collection<TransitiveInfoCollection>> entry :
         depsByArchitecture.asMap().entrySet()) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
index c8fe054..740f5c0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
@@ -34,12 +34,10 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /** A configuration containing flags required for Apple platforms and tools. */
@@ -444,7 +442,7 @@
   public static class Loader implements ConfigurationFragmentFactory {
     @Override
     public AppleConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions)
-        throws InvalidConfigurationException {
+        throws InvalidConfigurationException, InterruptedException {
       AppleCommandLineOptions appleOptions = buildOptions.get(AppleCommandLineOptions.class);
       XcodeVersionProperties xcodeVersionProperties = getXcodeVersionProperties(env, appleOptions);
 
@@ -487,18 +485,19 @@
     }
     
     /**
-     * Uses the {@link AppleCommandLineOptions#xcodeVersion} and
-     * {@link AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and
-     * return the effective xcode version properties. Returns absent if no explicit xcode version
-     * is declared, and host system defaults should be used.
+     * Uses the {@link AppleCommandLineOptions#xcodeVersion} and {@link
+     * AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and return the
+     * effective xcode version properties. Returns absent if no explicit xcode version is declared,
+     * and host system defaults should be used.
      *
      * @param env the current configuration environment
      * @param appleOptions the command line options
      * @throws InvalidConfigurationException if the options given (or configuration targets) were
      *     malformed and thus the xcode version could not be determined
      */
-    private XcodeVersionProperties getXcodeVersionProperties(ConfigurationEnvironment env,
-        AppleCommandLineOptions appleOptions) throws InvalidConfigurationException {
+    private static XcodeVersionProperties getXcodeVersionProperties(
+        ConfigurationEnvironment env, AppleCommandLineOptions appleOptions)
+        throws InvalidConfigurationException, InterruptedException {
       Optional<DottedVersion> xcodeVersionCommandLineFlag = 
           Optional.fromNullable(appleOptions.xcodeVersion);
       Label xcodeVersionConfigLabel = appleOptions.xcodeVersionConfig;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
index b4b2843..67a3d9e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
@@ -35,10 +35,8 @@
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
 import com.google.devtools.build.lib.syntax.Type;
-
 import java.util.List;
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -55,9 +53,9 @@
   }
   
   /**
-   * Uses the {@link AppleCommandLineOptions#xcodeVersion} and
-   * {@link AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and
-   * return the effective xcode version and its properties.
+   * Uses the {@link AppleCommandLineOptions#xcodeVersion} and {@link
+   * AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and return the
+   * effective xcode version and its properties.
    *
    * @param env the current configuration environment
    * @param xcodeConfigLabel the label for the xcode_config target to parse
@@ -68,9 +66,12 @@
    * @throws InvalidConfigurationException if the options given (or configuration targets) were
    *     malformed and thus the xcode version could not be determined
    */
-  public static XcodeVersionProperties resolveXcodeVersion(ConfigurationEnvironment env,
-      Label xcodeConfigLabel, Optional<DottedVersion> xcodeVersionOverrideFlag,
-      String errorDescription) throws InvalidConfigurationException {
+  static XcodeVersionProperties resolveXcodeVersion(
+      ConfigurationEnvironment env,
+      Label xcodeConfigLabel,
+      Optional<DottedVersion> xcodeVersionOverrideFlag,
+      String errorDescription)
+      throws InvalidConfigurationException, InterruptedException {
     Rule xcodeConfigRule =
         getRuleForLabel(xcodeConfigLabel, "xcode_config", env, errorDescription);
     
@@ -88,16 +89,18 @@
 
   /**
    * Returns the {@link XcodeVersionRuleData} associated with the {@code xcode_version} target
-   * explicitly defined in the {@code --xcode_version_config} build flag and selected by the
-   * {@code --xcode_version} flag. If {@code --xcode_version} is unspecified, then this
-   * will return the default rule data as specified in the {@code --xcode_version_config} target.
-   * Returns null if either the {@code --xcode_version} did not match any {@code xcode_version}
-   * target, or if {@code --xcode_version} is unspecified and {@code --xcode_version_config}
-   * specified no default target.
+   * explicitly defined in the {@code --xcode_version_config} build flag and selected by the {@code
+   * --xcode_version} flag. If {@code --xcode_version} is unspecified, then this will return the
+   * default rule data as specified in the {@code --xcode_version_config} target. Returns null if
+   * either the {@code --xcode_version} did not match any {@code xcode_version} target, or if {@code
+   * --xcode_version} is unspecified and {@code --xcode_version_config} specified no default target.
    */
-  @Nullable private static XcodeVersionRuleData resolveExplicitlyDefinedVersion(
-      ConfigurationEnvironment env, Rule xcodeConfigTarget,
-      Optional<DottedVersion> versionOverrideFlag) throws InvalidConfigurationException {
+  @Nullable
+  private static XcodeVersionRuleData resolveExplicitlyDefinedVersion(
+      ConfigurationEnvironment env,
+      Rule xcodeConfigTarget,
+      Optional<DottedVersion> versionOverrideFlag)
+      throws InvalidConfigurationException, InterruptedException {
 
     Map<String, XcodeVersionRuleData> aliasesToVersionMap =
         aliasesToVersionMap(env, xcodeConfigTarget);
@@ -129,11 +132,13 @@
   }
 
   /**
-   * Returns the default xcode version to use, if no {@code --xcode_version} command line flag
-   * was specified.
+   * Returns the default xcode version to use, if no {@code --xcode_version} command line flag was
+   * specified.
    */
-  @Nullable private static XcodeVersionRuleData getDefaultVersion(ConfigurationEnvironment env,
-      Rule xcodeConfigTarget) throws InvalidConfigurationException {
+  @Nullable
+  private static XcodeVersionRuleData getDefaultVersion(
+      ConfigurationEnvironment env, Rule xcodeConfigTarget)
+      throws InvalidConfigurationException, InterruptedException {
     Label defaultVersionLabel = NonconfigurableAttributeMapper.of(xcodeConfigTarget)
         .get(XcodeConfigRule.DEFAULT_ATTR_NAME, BuildType.LABEL);
     if (defaultVersionLabel != null) {
@@ -146,15 +151,15 @@
   }
 
   /**
-   * Returns a map where keys are "names" of xcode versions as defined by the configuration
-   * target, and values are the rule data objects which contain information regarding that
-   * xcode version.
+   * Returns a map where keys are "names" of xcode versions as defined by the configuration target,
+   * and values are the rule data objects which contain information regarding that xcode version.
    *
    * @throws InvalidConfigurationException if there are duplicate aliases (if two xcode versions
    *     were registered to the same alias)
    */
-  private static Map<String, XcodeVersionRuleData> aliasesToVersionMap(ConfigurationEnvironment env,
-      Rule xcodeConfigTarget) throws InvalidConfigurationException {
+  private static Map<String, XcodeVersionRuleData> aliasesToVersionMap(
+      ConfigurationEnvironment env, Rule xcodeConfigTarget)
+      throws InvalidConfigurationException, InterruptedException {
     List<Label> xcodeVersionLabels = NonconfigurableAttributeMapper.of(xcodeConfigTarget)
         .get(XcodeConfigRule.VERSIONS_ATTR_NAME, BuildType.LABEL_LIST);
     ImmutableList.Builder<XcodeVersionRuleData> xcodeVersionRuleListBuilder =
@@ -206,12 +211,13 @@
   }
 
   /**
-   * If the given label (following redirects) is a target for a rule of type {@code type},
-   * then returns the {@link Rule} representing that target. Otherwise, throws a
-   * {@link InvalidConfigurationException}.
+   * If the given label (following redirects) is a target for a rule of type {@code type}, then
+   * returns the {@link Rule} representing that target. Otherwise, throws a {@link
+   * InvalidConfigurationException}.
    */
-  private static Rule getRuleForLabel(Label label, String type, ConfigurationEnvironment env,
-      String description) throws InvalidConfigurationException {
+  private static Rule getRuleForLabel(
+      Label label, String type, ConfigurationEnvironment env, String description)
+      throws InvalidConfigurationException, InterruptedException {
     label = RedirectChaser.followRedirects(env, label, description);
 
     if (label == null) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
index 1856b04..d49415f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
@@ -396,7 +396,8 @@
       boolean fake,
       Artifact binary,
       LinkStaticness linkStaticness,
-      List<String> linkopts) {
+      List<String> linkopts)
+      throws InterruptedException {
     CppLinkActionBuilder builder =
         new CppLinkActionBuilder(context, binary)
             .setCrosstoolInputs(CppHelper.getToolchain(context).getLink())
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java
index 8e2a5aa..ead1c79 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java
@@ -24,13 +24,11 @@
 import com.google.devtools.build.lib.analysis.Runfiles;
 import com.google.devtools.build.lib.analysis.RunfilesProvider;
 import com.google.devtools.build.lib.analysis.actions.CreateIncSymlinkAction;
-import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
 import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
 import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
 import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider;
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -58,7 +56,8 @@
   }
   
   @Override
-  public ConfiguredTarget create(final RuleContext ruleContext) throws RuleErrorException {
+  public ConfiguredTarget create(final RuleContext ruleContext)
+      throws RuleErrorException, InterruptedException {
     FeatureConfiguration featureConfiguration = CcCommon.configureFeatures(ruleContext);
     PathFragment packageFragment = ruleContext.getPackageDirectory();
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
index 73fd709..3dd3f96 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
@@ -92,7 +92,8 @@
   }
 
   @Override
-  public ConfiguredTarget create(RuleContext context) throws RuleErrorException {
+  public ConfiguredTarget create(RuleContext context)
+      throws RuleErrorException, InterruptedException {
     RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(context);
     LinkTargetType linkType = getStaticLinkType(context);
     boolean linkStatic = context.attributes().get("linkstatic", Type.BOOLEAN);
@@ -113,7 +114,7 @@
       boolean linkStatic,
       boolean collectLinkstamp,
       boolean addDynamicRuntimeInputArtifactsToRunfiles)
-      throws RuleErrorException {
+      throws RuleErrorException, InterruptedException {
     FeatureConfiguration featureConfiguration = CcCommon.configureFeatures(ruleContext);
     final CcCommon common = new CcCommon(ruleContext);
     PrecompiledFiles precompiledFiles = new PrecompiledFiles(ruleContext);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
index 43d43dc..2b78db3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
@@ -868,7 +868,7 @@
    *
    * @throws RuleErrorException
    */
-  public Info build() throws RuleErrorException {
+  public Info build() throws RuleErrorException, InterruptedException {
     // Fail early if there is no lipo context collector on the rule - otherwise we end up failing
     // in lipo optimization.
     Preconditions.checkState(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
index f56ffdd..f24432d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
@@ -62,7 +62,8 @@
       new PathFragment("include/stdc-predef.h");
 
   @Override
-  public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException {
+  public ConfiguredTarget create(RuleContext ruleContext)
+      throws RuleErrorException, InterruptedException {
     TransitiveInfoCollection lipoContextCollector =
         ruleContext.getPrerequisite(":lipo_context_collector", Mode.DONT_CHECK);
     if (lipoContextCollector != null
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
index 91ff304..3769518 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
@@ -993,8 +993,10 @@
 
   @Override
   public Iterable<Artifact> resolveInputsFromCache(
-      ArtifactResolver artifactResolver, PackageRootResolver resolver,
-      Collection<PathFragment> inputPaths) throws PackageRootResolutionException {
+      ArtifactResolver artifactResolver,
+      PackageRootResolver resolver,
+      Collection<PathFragment> inputPaths)
+      throws PackageRootResolutionException, InterruptedException {
     // Note that this method may trigger a violation of the desirable invariant that getInputs()
     // is a superset of getMandatoryInputs(). See bug about an "action not in canonical form"
     // error message and the integration test test_crosstool_change_and_failure().
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
index e5097f0..c59480f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
@@ -39,7 +39,6 @@
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig;
-
 import javax.annotation.Nullable;
 
 /**
@@ -69,7 +68,7 @@
 
   @Override
   public CppConfiguration create(ConfigurationEnvironment env, BuildOptions options)
-      throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     CppConfigurationParameters params = createParameters(env, options);
     if (params == null) {
       return null;
@@ -113,7 +112,8 @@
 
   @Nullable
   protected CppConfigurationParameters createParameters(
-      ConfigurationEnvironment env, BuildOptions options) throws InvalidConfigurationException {
+      ConfigurationEnvironment env, BuildOptions options)
+      throws InvalidConfigurationException, InterruptedException {
     BlazeDirectories directories = env.getBlazeDirectories();
     if (directories == null) {
       return null;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
index ab0eb41..5268ff4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
@@ -425,7 +425,7 @@
   }
 
   /** Builds the Action as configured and returns it. */
-  public CppLinkAction build() {
+  public CppLinkAction build() throws InterruptedException {
     Preconditions.checkState(
         (libraryIdentifier == null) == (linkType == LinkTargetType.EXECUTABLE));
     if (interfaceOutput != null && (fake || linkType != LinkTargetType.DYNAMIC_LIBRARY)) {
@@ -1026,7 +1026,7 @@
    * #addLibraries}, and {@link #addLinkstamps}.
    */
   public CppLinkActionBuilder addLinkParams(
-      CcLinkParams linkParams, RuleErrorConsumer errorListener) {
+      CcLinkParams linkParams, RuleErrorConsumer errorListener) throws InterruptedException {
     addLinkopts(linkParams.flattenedLinkopts());
     addLibraries(linkParams.getLibraries());
     ExtraLinkTimeLibraries extraLinkTimeLibraries = linkParams.getExtraLinkTimeLibraries();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
index ba76f3e..8e0120e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
@@ -823,8 +823,9 @@
    *
    * @throws RuleErrorException
    */
-  public CcLinkingOutputs createCcLinkActions(CcCompilationOutputs ccOutputs,
-      Iterable<Artifact> nonCodeLinkerInputs) throws RuleErrorException {
+  public CcLinkingOutputs createCcLinkActions(
+      CcCompilationOutputs ccOutputs, Iterable<Artifact> nonCodeLinkerInputs)
+      throws RuleErrorException, InterruptedException {
     // For now only handle static links. Note that the dynamic library link below ignores linkType.
     // TODO(bazel-team): Either support non-static links or move this check to setLinkType().
     Preconditions.checkState(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
index 0a15404..d8fbe78 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
@@ -41,14 +41,12 @@
 import com.google.protobuf.TextFormat;
 import com.google.protobuf.TextFormat.ParseException;
 import com.google.protobuf.UninitializedMessageException;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
-
 import javax.annotation.Nullable;
 
 /**
@@ -171,7 +169,7 @@
   }
 
   private static CrosstoolProto getCrosstoolProtofromBuildFile(
-      ConfigurationEnvironment env, Label crosstoolTop) {
+      ConfigurationEnvironment env, Label crosstoolTop) throws InterruptedException {
     Target target;
     try {
       target = env.getTarget(crosstoolTop);
@@ -202,7 +200,7 @@
 
   private static CrosstoolProto getCrosstoolProtoFromCrosstoolFile(
       ConfigurationEnvironment env, Label crosstoolTop)
-      throws IOException, InvalidConfigurationException {
+      throws IOException, InvalidConfigurationException, InterruptedException {
     final Path path;
     try {
       Package containingPackage = env.getTarget(crosstoolTop.getLocalTargetLabel("BUILD"))
@@ -234,7 +232,7 @@
 
   private static CrosstoolFile findCrosstoolConfiguration(
       ConfigurationEnvironment env, Label crosstoolTop)
-      throws IOException, InvalidConfigurationException {
+      throws IOException, InvalidConfigurationException, InterruptedException {
 
     CrosstoolProto crosstoolProto = getCrosstoolProtofromBuildFile(env, crosstoolTop);
     if (crosstoolProto == null) {
@@ -267,12 +265,11 @@
     }
   }
 
-  /**
-   * Reads a crosstool file.
-   */
+  /** Reads a crosstool file. */
   @Nullable
   public static CrosstoolConfigurationLoader.CrosstoolFile readCrosstool(
-      ConfigurationEnvironment env, Label crosstoolTop) throws InvalidConfigurationException {
+      ConfigurationEnvironment env, Label crosstoolTop)
+      throws InvalidConfigurationException, InterruptedException {
     crosstoolTop = RedirectChaser.followRedirects(env, crosstoolTop, "crosstool_top");
     if (crosstoolTop == null) {
       return null;
@@ -400,9 +397,11 @@
   }
 
   public static CrosstoolConfig.CrosstoolRelease getCrosstoolReleaseProto(
-      ConfigurationEnvironment env, BuildOptions options,
-      Label crosstoolTop, Function<String, String> cpuTransformer)
-      throws InvalidConfigurationException {
+      ConfigurationEnvironment env,
+      BuildOptions options,
+      Label crosstoolTop,
+      Function<String, String> cpuTransformer)
+      throws InvalidConfigurationException, InterruptedException {
     CrosstoolConfigurationLoader.CrosstoolFile file =
         readCrosstool(env, crosstoolTop);
     // Make sure that we have the requested toolchain in the result. Throw an exception if not.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java
index 52b2a08..5daeb2d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java
@@ -32,10 +32,8 @@
  * context.
  */
 public interface ExtraLinkTimeLibrary {
-  /**
-   * Build the LibraryToLink inputs to pass to the C++ linker.
-   */
-  NestedSet<LibraryToLink> buildLibraries(RuleContext context);
+  /** Build the LibraryToLink inputs to pass to the C++ linker. */
+  NestedSet<LibraryToLink> buildLibraries(RuleContext context) throws InterruptedException;
 
   /**
    * Get a new Builder for this ExtraLinkTimeLibrary class.  This acts
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java
index 747ea82..db3fbf1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java
@@ -38,7 +38,6 @@
 import com.google.devtools.build.lib.vfs.ZipFileSystem;
 import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.LipoMode;
 import com.google.devtools.build.skyframe.SkyFunction;
-
 import java.io.IOException;
 import java.util.Collection;
 import java.util.zip.ZipException;
@@ -233,11 +232,14 @@
     return fdoRoot;
   }
 
-  /**
-   * Creates an initialized {@link FdoSupport} instance.
-   */
-  static FdoSupport create(SkyFunction.Environment env, PathFragment fdoInstrument,
-      Path fdoProfile, LipoMode lipoMode, Path execRoot) throws IOException, FdoException {
+  /** Creates an initialized {@link FdoSupport} instance. */
+  static FdoSupport create(
+      SkyFunction.Environment env,
+      PathFragment fdoInstrument,
+      Path fdoProfile,
+      LipoMode lipoMode,
+      Path execRoot)
+      throws IOException, FdoException, InterruptedException {
     FdoMode fdoMode;
     if (fdoProfile != null && isAutoFdo(fdoProfile.getBaseName())) {
       fdoMode = FdoMode.AUTO_FDO;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/extra/ExtraAction.java b/src/main/java/com/google/devtools/build/lib/rules/extra/ExtraAction.java
index 88c967a..ef3e620 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/extra/ExtraAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/extra/ExtraAction.java
@@ -39,12 +39,10 @@
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.GuardedBy;
 
@@ -165,9 +163,11 @@
 
   @Nullable
   @Override
-  public Iterable<Artifact> resolveInputsFromCache(ArtifactResolver artifactResolver,
-      PackageRootResolver resolver, Collection<PathFragment> inputPaths)
-          throws PackageRootResolutionException {
+  public Iterable<Artifact> resolveInputsFromCache(
+      ArtifactResolver artifactResolver,
+      PackageRootResolver resolver,
+      Collection<PathFragment> inputPaths)
+      throws PackageRootResolutionException, InterruptedException {
     // We update the inputs directly from the shadowed action.
     Set<PathFragment> extraActionPathFragments =
         ImmutableSet.copyOf(Artifact.asPathFragments(extraActionInputs));
diff --git a/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java b/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java
index c5ebb6f..2a336da 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java
@@ -44,7 +44,6 @@
 import com.google.devtools.build.lib.packages.NoSuchPackageException;
 import com.google.devtools.build.lib.packages.NoSuchTargetException;
 import com.google.devtools.build.lib.packages.Package;
-import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.pkgcache.FilteringPolicies;
 import com.google.devtools.build.lib.pkgcache.FilteringPolicy;
@@ -78,7 +77,6 @@
 import com.google.devtools.build.skyframe.ValueOrException;
 import com.google.devtools.common.options.OptionsParser;
 import com.google.devtools.common.options.OptionsParsingException;
-
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -89,7 +87,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -168,7 +165,7 @@
 
   // The transitive closure of these targets is an upper estimate on the labels
   // the query will touch
-  private Set<Target> getScope(RuleContext context) {
+  private static Set<Target> getScope(RuleContext context) throws InterruptedException {
     List<Label> scopeLabels = context.attributes().get("scope", BuildType.LABEL_LIST);
     Set<Target> scope = Sets.newHashSetWithExpectedSize(scopeLabels.size());
     for (Label scopePart : scopeLabels) {
@@ -199,8 +196,9 @@
   }
 
   @Nullable
-  private Pair<ImmutableMap<PackageIdentifier, Package>, ImmutableMap<Label, Target>>
-  constructPackageMap(SkyFunction.Environment env, Collection<Target> scope) {
+  private static Pair<ImmutableMap<PackageIdentifier, Package>, ImmutableMap<Label, Target>>
+      constructPackageMap(SkyFunction.Environment env, Collection<Target> scope)
+          throws InterruptedException {
     // It is not necessary for correctness to construct intermediate NestedSets; we could iterate
     // over individual targets in scope immediately. However, creating a composite NestedSet first
     // saves us from iterating over the same sub-NestedSets multiple times.
@@ -374,10 +372,9 @@
     }
 
     @Override
-    public Map<String, ResolvedTargets<Target>> preloadTargetPatterns(EventHandler eventHandler,
-                                                               Collection<String> patterns,
-                                                               boolean keepGoing)
-        throws TargetParsingException {
+    public Map<String, ResolvedTargets<Target>> preloadTargetPatterns(
+        EventHandler eventHandler, Collection<String> patterns, boolean keepGoing)
+        throws TargetParsingException, InterruptedException {
       Preconditions.checkArgument(!keepGoing);
       boolean ok = true;
       Map<String, ResolvedTargets<Target>> preloadedPatterns =
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java
index 3e2b13a..43b5676 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java
@@ -25,11 +25,9 @@
 import com.google.devtools.build.lib.analysis.actions.SpawnAction;
 import com.google.devtools.build.lib.collect.IterablesChain;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -193,10 +191,8 @@
     return args;
   }
 
-  /**
-   * Builds the action as configured.
-   */
-  public void build() {
+  /** Builds the action as configured. */
+  public void build() throws InterruptedException {
     ImmutableList<Artifact> classpathResources = attributes.getClassPathResources();
     Set<String> classPathResourceNames = new HashSet<>();
     for (Artifact artifact : classpathResources) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java
index a87e5b4..934437c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java
@@ -51,14 +51,12 @@
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -176,8 +174,13 @@
    * Creates an action to aggregate all metadata artifacts into a single
    * &lt;target_name&gt;_instrumented.jar file.
    */
-  public static void createInstrumentedJarAction(RuleContext ruleContext, JavaSemantics semantics,
-      List<Artifact> metadataArtifacts, Artifact instrumentedJar, String mainClass) {
+  public static void createInstrumentedJarAction(
+      RuleContext ruleContext,
+      JavaSemantics semantics,
+      List<Artifact> metadataArtifacts,
+      Artifact instrumentedJar,
+      String mainClass)
+      throws InterruptedException {
     // In Jacoco's setup, metadata artifacts are real jars.
     new DeployArchiveBuilder(semantics, ruleContext)
         .setOutputJar(instrumentedJar)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java
index c6eda48..6ae2f22 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java
@@ -41,7 +41,7 @@
 
   @Override
   public JavaConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions)
-      throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     CppConfiguration cppConfiguration = env.getFragment(buildOptions, CppConfiguration.class);
     if (cppConfiguration == null) {
       return null;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java
index 4424789..fa665c4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java
@@ -265,10 +265,14 @@
    *
    * @return new main class
    */
-  String addCoverageSupport(JavaCompilationHelper helper,
+  String addCoverageSupport(
+      JavaCompilationHelper helper,
       JavaTargetAttributes.Builder attributes,
-      Artifact executable, Artifact instrumentationMetadata,
-      JavaCompilationArtifacts.Builder javaArtifactsBuilder, String mainClass);
+      Artifact executable,
+      Artifact instrumentationMetadata,
+      JavaCompilationArtifacts.Builder javaArtifactsBuilder,
+      String mainClass)
+      throws InterruptedException;
 
   /**
    * Return the JVM flags to be used in a Java binary.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java
index c127140..904f863 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java
@@ -34,9 +34,7 @@
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.List;
-
 import javax.annotation.Nullable;
 
 /**
@@ -60,7 +58,7 @@
 
   @Override
   public Jvm create(ConfigurationEnvironment env, BuildOptions buildOptions)
-      throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     JavaOptions javaOptions = buildOptions.get(JavaOptions.class);
     if (javaOptions.disableJvm) {
       // TODO(bazel-team): Instead of returning null here, add another method to the interface.
@@ -92,8 +90,8 @@
   }
 
   @Nullable
-  private Jvm createDefault(ConfigurationEnvironment lookup, String javaHome, String cpu)
-      throws InvalidConfigurationException, LabelSyntaxException {
+  private static Jvm createDefault(ConfigurationEnvironment lookup, String javaHome, String cpu)
+      throws InvalidConfigurationException, LabelSyntaxException, InterruptedException {
     try {
       Label label = Label.parseAbsolute(javaHome);
       label = RedirectChaser.followRedirects(lookup, label, "jdk");
diff --git a/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java b/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java
index 8b9f9fe..b9896e9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java
@@ -87,13 +87,16 @@
    *
    * @param ruleContext the rule context to determine the native deps library
    * @param linkParams the {@link CcLinkParams} for the rule, collected with linkstatic = 1 and
-   *        linkshared = 1
+   *     linkshared = 1
    * @return the native deps library runfiles. If the transitive deps closure of the rule contains
-   *         no native code libraries, its fields are null.
+   *     no native code libraries, its fields are null.
    */
-  public static Artifact maybeCreateAndroidNativeDepsAction(final RuleContext ruleContext,
-      CcLinkParams linkParams, final BuildConfiguration configuration,
-      CcToolchainProvider toolchain) {
+  public static Artifact maybeCreateAndroidNativeDepsAction(
+      final RuleContext ruleContext,
+      CcLinkParams linkParams,
+      final BuildConfiguration configuration,
+      CcToolchainProvider toolchain)
+      throws InterruptedException {
     if (linkParams.getLibraries().isEmpty()) {
       return null;
     }
@@ -128,7 +131,8 @@
       Artifact nativeDeps,
       String libraryIdentifier,
       Root bindirIfShared,
-      boolean useDynamicRuntime) {
+      boolean useDynamicRuntime)
+      throws InterruptedException {
     Preconditions.checkState(
         ruleContext.isLegalFragment(CppConfiguration.class),
         "%s does not have access to CppConfiguration",
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java
index cb8503d..a23a234 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java
@@ -30,7 +30,7 @@
 public class ObjcConfigurationLoader implements ConfigurationFragmentFactory {
   @Override
   public ObjcConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions)
-      throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     Options options = buildOptions.get(BuildConfiguration.Options.class);
     ObjcCommandLineOptions objcOptions = buildOptions.get(ObjcCommandLineOptions.class);
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java
index 39e6d2c..c870acc 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java
@@ -312,7 +312,7 @@
     return this;
   }
 
-  private void registerEmbedLabelPlistAction() {
+  private void registerEmbedLabelPlistAction() throws InterruptedException {
     Artifact buildInfo = Iterables.getOnlyElement(
         ruleContext.getBuildInfo(ObjcBuildInfoFactory.KEY));
     String generatedVersionPlistPath = getGeneratedVersionPlist().getShellEscapedExecPathString();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java
index 2599cb1..ff49b2d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java
@@ -26,7 +26,6 @@
 import com.google.devtools.build.lib.rules.cpp.CppOptions;
 import com.google.devtools.build.lib.rules.cpp.CrosstoolConfigurationLoader;
 import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig;
-
 import javax.annotation.Nullable;
 
 /**
@@ -47,7 +46,7 @@
   @Nullable
   private CrosstoolConfig.CToolchain getToolchain(
       ConfigurationEnvironment env, BuildOptions buildOptions, Label crosstoolTop)
-      throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     CrosstoolConfigurationLoader.CrosstoolFile file =
         CrosstoolConfigurationLoader.readCrosstool(env, crosstoolTop);
     if (file == null) {
@@ -59,7 +58,7 @@
 
   @Override
   public PythonConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions)
-      throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     PythonOptions pythonOptions = buildOptions.get(PythonOptions.class);
     CppConfiguration cppConfiguration = env.getFragment(buildOptions, CppConfiguration.class);
     if (cppConfiguration == null) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java
index d45a809..08fcb1b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java
@@ -41,10 +41,9 @@
    */
   void collectRunfilesForBinary(RuleContext ruleContext, Runfiles.Builder builder, PyCommon common);
 
- /**
-   * Extends the default runfiles of {@code py_binary} rules with custom elements.
-   */
-  void collectDefaultRunfilesForBinary(RuleContext ruleContext, Runfiles.Builder builder);
+  /** Extends the default runfiles of {@code py_binary} rules with custom elements. */
+  void collectDefaultRunfilesForBinary(RuleContext ruleContext, Runfiles.Builder builder)
+      throws InterruptedException;
 
   /**
    * Returns the coverage instrumentation specification to be used in Python rules.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java
index 258cb96..b5f9071 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java
@@ -21,10 +21,8 @@
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
-import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.io.IOException;
 
 /**
@@ -40,7 +38,7 @@
   @Override
   public SkyValue fetch(
       Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env)
-      throws SkyFunctionException {
+      throws InterruptedException, RepositoryFunctionException {
     PathFragment pathFragment = RepositoryFunction.getTargetPath(rule, directories.getWorkspace());
     try {
       outputDirectory.createSymbolicLink(pathFragment);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java
index eb77b57..db79483 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java
@@ -27,7 +27,6 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.io.IOException;
 
 /**
@@ -43,7 +42,7 @@
   @Override
   public SkyValue fetch(
       Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env)
-      throws SkyFunctionException {
+      throws SkyFunctionException, InterruptedException {
 
     NewRepositoryBuildFileHandler buildFileHandler =
         new NewRepositoryBuildFileHandler(directories.getWorkspace());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryBuildFileHandler.java b/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryBuildFileHandler.java
index 456d808..18654e1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryBuildFileHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryBuildFileHandler.java
@@ -32,7 +32,6 @@
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyKey;
-
 import java.io.IOException;
 
 /**
@@ -59,7 +58,7 @@
    *     retrieved, written, or symlinked.
    */
   public boolean prepareBuildFile(Rule rule, Environment env)
-      throws RepositoryFunctionException {
+      throws RepositoryFunctionException, InterruptedException {
 
     AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
     boolean hasBuildFile = mapper.isAttributeValueExplicitlySpecified("build_file");
@@ -115,7 +114,7 @@
   }
 
   private FileValue getBuildFileValue(Rule rule, Environment env)
-      throws RepositoryFunctionException {
+      throws RepositoryFunctionException, InterruptedException {
     AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
     String buildFileAttribute = mapper.get("build_file", Type.STRING);
     RootedPath rootedBuild;
@@ -200,4 +199,4 @@
     Path buildFilePath = outputDirectory.getRelative("BUILD");
     RepositoryFunction.createSymbolicLink(buildFilePath, buildFileValue.realRootedPath().asPath());
   }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
index 98e4ad9..cb01f31 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
@@ -132,21 +132,22 @@
    *
    * <p>The {@code env} argument can be used to fetch Skyframe dependencies the repository
    * implementation needs on the following conditions:
+   *
    * <ul>
-   *   <li>When a Skyframe value is missing, fetching must be restarted, thus, in order to avoid
-   *     doing duplicate work, it's better to first request the Skyframe dependencies you need and
-   *     only then start doing anything costly.
-   *   <li>The output directory must be populated from within this method (and not from within
-   *     another SkyFunction). This is because if it was populated in another SkyFunction, the
-   *     repository function would be restarted <b>after</b> that SkyFunction has been run, and
-   *     it would wipe the output directory clean.
+   * <li>When a Skyframe value is missing, fetching must be restarted, thus, in order to avoid doing
+   *     duplicate work, it's better to first request the Skyframe dependencies you need and only
+   *     then start doing anything costly.
+   * <li>The output directory must be populated from within this method (and not from within another
+   *     SkyFunction). This is because if it was populated in another SkyFunction, the repository
+   *     function would be restarted <b>after</b> that SkyFunction has been run, and it would wipe
+   *     the output directory clean.
    * </ul>
    */
   @ThreadSafe
   @Nullable
   public abstract SkyValue fetch(
       Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env)
-          throws SkyFunctionException, InterruptedException;
+      throws SkyFunctionException, InterruptedException;
 
   /**
    * Whether fetching is done using local operations only.
@@ -164,7 +165,7 @@
    * to keep it working somehow)
    */
   protected byte[] getRuleSpecificMarkerData(Rule rule, Environment env)
-      throws RepositoryFunctionException {
+      throws RepositoryFunctionException, InterruptedException {
     return new byte[] {};
   }
 
@@ -265,7 +266,7 @@
    */
   @Nullable
   public static Rule getRule(String repository, Environment env)
-      throws RepositoryFunctionException {
+      throws RepositoryFunctionException, InterruptedException {
 
     SkyKey packageLookupKey = PackageLookupValue.key(Label.EXTERNAL_PACKAGE_IDENTIFIER);
     PackageLookupValue packageLookupValue = (PackageLookupValue) env.getValue(packageLookupKey);
@@ -298,9 +299,8 @@
   }
 
   @Nullable
-  public static Rule getRule(
-      String ruleName, @Nullable String ruleClassName, Environment env)
-          throws RepositoryFunctionException {
+  public static Rule getRule(String ruleName, @Nullable String ruleClassName, Environment env)
+      throws RepositoryFunctionException, InterruptedException {
     try {
       return getRule(RepositoryName.create("@" + ruleName), ruleClassName, env);
     } catch (LabelSyntaxException e) {
@@ -310,15 +310,15 @@
   }
 
   /**
-   * Uses a remote repository name to fetch the corresponding Rule describing how to get it.
-   * This should be called from {@link SkyFunction#compute} functions, which should return null if
-   * this returns null. If {@code ruleClassName} is set, the rule found must have a matching rule
-   * class name.
+   * Uses a remote repository name to fetch the corresponding Rule describing how to get it. This
+   * should be called from {@link SkyFunction#compute} functions, which should return null if this
+   * returns null. If {@code ruleClassName} is set, the rule found must have a matching rule class
+   * name.
    */
   @Nullable
   public static Rule getRule(
       RepositoryName repositoryName, @Nullable String ruleClassName, Environment env)
-          throws RepositoryFunctionException {
+      throws RepositoryFunctionException, InterruptedException {
     Rule rule = getRule(repositoryName.strippedName(), env);
     Preconditions.checkState(
         rule == null || ruleClassName == null || rule.getRuleClass().equals(ruleClassName),
@@ -327,12 +327,12 @@
   }
 
   /**
-   * Adds the repository's directory to the graph and, if it's a symlink, resolves it to an
-   * actual directory.
+   * Adds the repository's directory to the graph and, if it's a symlink, resolves it to an actual
+   * directory.
    */
   @Nullable
-  public static FileValue getRepositoryDirectory(Path repositoryDirectory, Environment env)
-      throws RepositoryFunctionException {
+  protected static FileValue getRepositoryDirectory(Path repositoryDirectory, Environment env)
+      throws RepositoryFunctionException, InterruptedException {
     SkyKey outputDirectoryKey = FileValue.key(RootedPath.toRootedPath(
         repositoryDirectory, PathFragment.EMPTY_FRAGMENT));
     FileValue value;
@@ -354,21 +354,19 @@
   }
 
   /**
-   * For files that are under $OUTPUT_BASE/external, add a dependency on the corresponding rule
-   * so that if the WORKSPACE file changes, the File/DirectoryStateValue will be re-evaluated.
+   * For files that are under $OUTPUT_BASE/external, add a dependency on the corresponding rule so
+   * that if the WORKSPACE file changes, the File/DirectoryStateValue will be re-evaluated.
    *
-   * Note that:
-   * - We don't add a dependency on the parent directory at the package root boundary, so
-   * the only transitive dependencies from files inside the package roots to external files
-   * are through symlinks. So the upwards transitive closure of external files is small.
-   * - The only way other than external repositories for external source files to get into the
-   * skyframe graph in the first place is through symlinks outside the package roots, which we
-   * neither want to encourage nor optimize for since it is not common. So the set of external
-   * files is small.
+   * <p>Note that: - We don't add a dependency on the parent directory at the package root boundary,
+   * so the only transitive dependencies from files inside the package roots to external files are
+   * through symlinks. So the upwards transitive closure of external files is small. - The only way
+   * other than external repositories for external source files to get into the skyframe graph in
+   * the first place is through symlinks outside the package roots, which we neither want to
+   * encourage nor optimize for since it is not common. So the set of external files is small.
    */
   public static void addExternalFilesDependencies(
       RootedPath rootedPath, BlazeDirectories directories, Environment env)
-      throws IOException {
+      throws IOException, InterruptedException {
     Path externalRepoDir = getExternalRepositoryDirectory(directories);
     PathFragment repositoryPath = rootedPath.asPath().relativeTo(externalRepoDir);
     if (repositoryPath.segmentCount() == 0) {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
index 7ba1e2d..3f0dc5c 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
@@ -34,7 +34,6 @@
 import com.google.devtools.common.options.OptionsBase;
 import com.google.devtools.common.options.OptionsParser;
 import com.google.devtools.common.options.OptionsProvider;
-
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
@@ -188,6 +187,8 @@
       return e.getExitCode();
     } catch (IOException e) {
       return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
+    } catch (InterruptedException e) {
+      return ExitCode.INTERRUPTED;
     }
     return ExitCode.SUCCESS;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java
index 4677b4a..52c9991 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java
@@ -94,10 +94,12 @@
 
   /**
    * Returns the value of the info key. The return value is directly printed to stdout.
+   *
    * @param env TODO(lpino):
    */
-  public abstract byte[] get(Supplier<BuildConfiguration> configurationSupplier,
-      CommandEnvironment env) throws AbruptExitException;
+  public abstract byte[] get(
+      Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+      throws AbruptExitException, InterruptedException;
 
   private static byte[] print(Object value) {
     if (value instanceof byte[]) {
@@ -626,4 +628,4 @@
       return print(description);
     }
   }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
index 8ec6f0e..19fb401 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
@@ -196,11 +196,12 @@
    * the action cache's view of this action contains additional inputs, it will request metadata for
    * them, so we consider those inputs as dependencies of this action as well. Returns null if some
    * dependencies were missing and this ActionExecutionFunction needs to restart.
+   *
    * @throws ActionExecutionFunctionException
    */
   @Nullable
   private AllInputs collectInputs(Action action, Environment env)
-      throws ActionExecutionFunctionException {
+      throws ActionExecutionFunctionException, InterruptedException {
     Iterable<Artifact> allKnownInputs = Iterables.concat(
         action.getInputs(), action.getRunfilesSupplier().getArtifacts());
     if (action.inputsKnown()) {
@@ -264,7 +265,7 @@
 
     @Override
     public Map<PathFragment, Root> findPackageRootsForFiles(Iterable<PathFragment> execPaths)
-        throws PackageRootResolutionException {
+        throws PackageRootResolutionException, InterruptedException {
       Preconditions.checkState(keysRequested.isEmpty(),
           "resolver should only be called once: %s %s", keysRequested, execPaths);
       // Create SkyKeys list based on execPaths.
@@ -316,7 +317,7 @@
     @Override
     @Nullable
     public Map<PathFragment, Root> findPackageRoots(Iterable<PathFragment> execPaths)
-        throws PackageRootResolutionException {
+        throws PackageRootResolutionException, InterruptedException {
       // call sites for this implementation of PackageRootResolver shouldn't be passing in
       // directories.
       return findPackageRootsForFiles(execPaths);
@@ -454,8 +455,10 @@
   }
 
   private static void addDiscoveredInputs(
-      Map<Artifact, FileArtifactValue> inputData, Iterable<Artifact> discoveredInputs,
-      Environment env) {
+      Map<Artifact, FileArtifactValue> inputData,
+      Iterable<Artifact> discoveredInputs,
+      Environment env)
+      throws InterruptedException {
     Set<SkyKey> keys = new HashSet<>();
     for (Artifact artifact : discoveredInputs) {
       if (!inputData.containsKey(artifact)) {
@@ -479,8 +482,8 @@
     }
   }
 
-  private void establishSkyframeDependencies(Environment env, Action action)
-      throws ActionExecutionException {
+  private static void establishSkyframeDependencies(Environment env, Action action)
+      throws ActionExecutionException, InterruptedException {
     // Before we may safely establish Skyframe dependencies, we must build all action inputs by
     // requesting their ArtifactValues.
     // This is very important to do, because the establishSkyframeDependencies method may request
@@ -619,12 +622,12 @@
   }
 
   /**
-   * Declares skyframe dependencies for any {@code action}'s inputs that are not already in
-   * {@code knownInputs}. Returns the result of {@code env.getValues(...)} for these inputs,
-   * which should contain {@link Artifact} keys and {@link FileArtifactValue} or null values.
+   * Declares skyframe dependencies for any {@code action}'s inputs that are not already in {@code
+   * knownInputs}. Returns the result of {@code env.getValues(...)} for these inputs, which should
+   * contain {@link Artifact} keys and {@link FileArtifactValue} or null values.
    */
-  private static Map<SkyKey, SkyValue> declareAdditionalDependencies(Environment env,
-      Action action, Set<Artifact> knownInputs) {
+  private static Map<SkyKey, SkyValue> declareAdditionalDependencies(
+      Environment env, Action action, Set<Artifact> knownInputs) throws InterruptedException {
     Preconditions.checkState(action.discoversInputs(), action);
     Iterable<Artifact> newArtifacts =
         Iterables.filter(action.getInputs(), Predicates.not(Predicates.in(knownInputs)));
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionTemplateExpansionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionTemplateExpansionFunction.java
index 59572f1..6a18db7 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionTemplateExpansionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionTemplateExpansionFunction.java
@@ -38,7 +38,7 @@
 
   @Override
   public SkyValue compute(SkyKey skyKey, Environment env)
-      throws ActionTemplateExpansionFunctionException {
+      throws ActionTemplateExpansionFunctionException, InterruptedException {
     ActionTemplateExpansionKey key = (ActionTemplateExpansionKey) skyKey.argument();
     SpawnActionTemplate actionTemplate = key.getActionTemplate();
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
index f7007b7..cecc089 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
@@ -54,7 +54,8 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) throws ArtifactFunctionException {
+  public SkyValue compute(SkyKey skyKey, Environment env)
+      throws ArtifactFunctionException, InterruptedException {
     OwnedArtifact ownedArtifact = (OwnedArtifact) skyKey.argument();
     Artifact artifact = ownedArtifact.getArtifact();
     if (artifact.isSourceArtifact()) {
@@ -116,9 +117,9 @@
     }
   }
 
-  private TreeArtifactValue createTreeArtifactValueFromActionTemplate(
+  private static TreeArtifactValue createTreeArtifactValueFromActionTemplate(
       SpawnActionTemplate actionTemplate, Artifact treeArtifact, Environment env)
-      throws ArtifactFunctionException {
+      throws ArtifactFunctionException, InterruptedException {
     // Request the list of expanded actions from the ActionTemplate.
     ActionTemplateExpansionValue expansionValue = (ActionTemplateExpansionValue) env.getValue(
         ActionTemplateExpansionValue.key(actionTemplate));
@@ -167,7 +168,7 @@
   }
 
   private FileArtifactValue createSourceValue(Artifact artifact, boolean mandatory, Environment env)
-      throws MissingInputFileException {
+      throws MissingInputFileException, InterruptedException {
     SkyKey fileSkyKey = FileValue.key(RootedPath.toRootedPath(artifact.getRoot().getPath(),
         artifact.getPath()));
     FileValue fileValue;
@@ -253,7 +254,8 @@
       Artifact artifact,
       ActionAnalysisMetadata action,
       FileArtifactValue value,
-      SkyFunction.Environment env) {
+      SkyFunction.Environment env)
+      throws InterruptedException {
     // This artifact aggregates other artifacts. Keep track of them so callers can find them.
     ImmutableList.Builder<Pair<Artifact, FileArtifactValue>> inputs = ImmutableList.builder();
     for (Map.Entry<SkyKey, SkyValue> entry :
@@ -286,8 +288,8 @@
     return Label.print(((OwnedArtifact) skyKey.argument()).getArtifact().getOwner());
   }
 
-  private ActionAnalysisMetadata extractActionFromArtifact(
-      Artifact artifact, SkyFunction.Environment env) {
+  private static ActionAnalysisMetadata extractActionFromArtifact(
+      Artifact artifact, SkyFunction.Environment env) throws InterruptedException {
     ArtifactOwner artifactOwner = artifact.getArtifactOwner();
 
     Preconditions.checkState(artifactOwner instanceof ActionLookupKey, "", artifact, artifactOwner);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
index c1f8c33..d94be28 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
@@ -57,7 +57,6 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import javax.annotation.Nullable;
 
 /**
@@ -93,9 +92,9 @@
    * @return {@code null} if dependencies cannot be satisfied.
    */
   @Nullable
-  public static SkylarkAspect loadSkylarkAspect(
+  static SkylarkAspect loadSkylarkAspect(
       Environment env, Label extensionLabel, String skylarkValueName)
-          throws AspectCreationException {
+      throws AspectCreationException, InterruptedException {
     SkyKey importFileKey = SkylarkImportLookupValue.key(extensionLabel, false);
     try {
       SkylarkImportLookupValue skylarkImportLookupValue =
@@ -275,8 +274,13 @@
     }
   }
 
-  private SkyValue createAliasAspect(Environment env, Target originalTarget, Label aliasLabel,
-      Aspect aspect, AspectKey originalKey) {
+  private static SkyValue createAliasAspect(
+      Environment env,
+      Target originalTarget,
+      Label aliasLabel,
+      Aspect aspect,
+      AspectKey originalKey)
+      throws InterruptedException {
     SkyKey depKey = AspectValue.key(aliasLabel,
         originalKey.getAspectConfiguration(),
         originalKey.getBaseConfiguration(),
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java
index a25c3ac..3f18f85 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java
@@ -29,7 +29,6 @@
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
 import com.google.devtools.build.skyframe.ValueOrException;
-
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
@@ -52,7 +51,8 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
+  public SkyValue compute(SkyKey skyKey, Environment env)
+      throws InterruptedException, BuildConfigurationFunctionException {
     BuildConfigurationValue.Key key = (BuildConfigurationValue.Key) skyKey.argument();
     Set<Fragment> fragments;
     try {
@@ -83,7 +83,7 @@
   }
 
   private Set<Fragment> getConfigurationFragments(BuildConfigurationValue.Key key, Environment env)
-      throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
 
     // Get SkyKeys for the fragments we need to load.
     Set<SkyKey> fragmentKeys = new LinkedHashSet<>();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java
index 5edaf98..7361c1f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java
@@ -26,7 +26,6 @@
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.Map;
 
 /**
@@ -46,7 +45,7 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) {
+  public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
     final BuildInfoKeyAndConfig keyAndConfig = (BuildInfoKeyAndConfig) skyKey.argument();
     WorkspaceStatusValue infoArtifactValue =
         (WorkspaceStatusValue) env.getValue(WorkspaceStatusValue.SKY_KEY);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryFunction.java
index 21d4eb2..cef2a10 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryFunction.java
@@ -25,9 +25,7 @@
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -44,7 +42,7 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) {
+  public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
     return new MyTraversalFunction().visitDirectory((RecursivePkgKey) skyKey.argument(), env);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java
index db9ab97..6a3e6e4 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java
@@ -46,15 +46,11 @@
 public final class CompletionFunction<TValue extends SkyValue, TResult extends SkyValue>
     implements SkyFunction {
 
-  /**
-   * A strategy for completing the build.
-   */
-  public interface Completor<TValue, TResult extends SkyValue> {
+  /** A strategy for completing the build. */
+  interface Completor<TValue, TResult extends SkyValue> {
 
-    /**
-     * Obtains an analysis result value from environment.
-     */
-    TValue getValueFromSkyKey(SkyKey skyKey, Environment env);
+    /** Obtains an analysis result value from environment. */
+    TValue getValueFromSkyKey(SkyKey skyKey, Environment env) throws InterruptedException;
 
     /**
      * Returns the options which determine the artifacts to build for the top-level targets.
@@ -104,7 +100,8 @@
   private static class TargetCompletor
       implements Completor<ConfiguredTargetValue, TargetCompletionValue> {
     @Override
-    public ConfiguredTargetValue getValueFromSkyKey(SkyKey skyKey, Environment env) {
+    public ConfiguredTargetValue getValueFromSkyKey(SkyKey skyKey, Environment env)
+        throws InterruptedException {
       TargetCompletionKey tcKey = (TargetCompletionKey) skyKey.argument();
       LabelAndConfiguration lac = tcKey.labelAndConfiguration();
       return (ConfiguredTargetValue)
@@ -162,7 +159,8 @@
 
   private static class AspectCompletor implements Completor<AspectValue, AspectCompletionValue> {
     @Override
-    public AspectValue getValueFromSkyKey(SkyKey skyKey, Environment env) {
+    public AspectValue getValueFromSkyKey(SkyKey skyKey, Environment env)
+        throws InterruptedException {
       AspectCompletionKey acKey = (AspectCompletionKey) skyKey.argument();
       AspectKey aspectKey = acKey.aspectKey();
       return (AspectValue) env.getValue(AspectValue.key(aspectKey));
@@ -237,7 +235,8 @@
 
   @Nullable
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) throws CompletionFunctionException {
+  public SkyValue compute(SkyKey skyKey, Environment env)
+      throws CompletionFunctionException, InterruptedException {
     TValue value = completor.getValueFromSkyKey(skyKey, env);
     TopLevelArtifactContext topLevelContext = completor.getTopLevelArtifactContext(skyKey);
     if (env.valuesMissing()) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationCollectionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationCollectionFunction.java
index d50e2a6..e73b2b4 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationCollectionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationCollectionFunction.java
@@ -33,10 +33,8 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.ArrayList;
 import java.util.List;
-
 import javax.annotation.Nullable;
 
 /**
@@ -75,10 +73,12 @@
   }
 
   /** Create the build configurations with the given options. */
-  private BuildConfigurationCollection getConfigurations(Environment env,
-      PackageProviderForConfigurations loadedPackageProvider, BuildOptions buildOptions,
+  private BuildConfigurationCollection getConfigurations(
+      Environment env,
+      PackageProviderForConfigurations loadedPackageProvider,
+      BuildOptions buildOptions,
       ImmutableSet<String> multiCpu)
-          throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     // We cache all the related configurations for this target configuration in a cache that is
     // dropped at the end of this method call. We instead rely on the cache for entire collections
     // for caching the target and related configurations, and on a dedicated host configuration
@@ -115,11 +115,10 @@
     return new BuildConfigurationCollection(targetConfigurations, hostConfiguration);
   }
 
-  /**
-   * Returns the host configuration, or null on missing Skyframe deps.
-   */
-  private BuildConfiguration getHostConfiguration(Environment env,
-      BuildConfiguration targetConfiguration) throws InvalidConfigurationException {
+  /** Returns the host configuration, or null on missing Skyframe deps. */
+  private static BuildConfiguration getHostConfiguration(
+      Environment env, BuildConfiguration targetConfiguration)
+      throws InvalidConfigurationException, InterruptedException {
     if (targetConfiguration.useDynamicConfigurations()) {
       BuildOptions hostOptions = HostTransition.INSTANCE.apply(targetConfiguration.getOptions());
       SkyKey hostConfigKey =
@@ -149,7 +148,9 @@
       Cache<String, BuildConfiguration> cache,
       EventHandler originalEventListener,
       PackageProviderForConfigurations loadedPackageProvider,
-      BuildOptions buildOptions, String cpuOverride) throws InvalidConfigurationException {
+      BuildOptions buildOptions,
+      String cpuOverride)
+      throws InvalidConfigurationException, InterruptedException {
     ErrorSensingEventHandler eventHandler = new ErrorSensingEventHandler(originalEventListener);
     if (cpuOverride != null) {
       // TODO(bazel-team): Options classes should be immutable. This is a bit of a hack.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationFragmentFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationFragmentFunction.java
index f2a12e7..62bee58 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationFragmentFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationFragmentFunction.java
@@ -43,7 +43,6 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.io.IOException;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -100,8 +99,11 @@
    * those returned from {@link BuildOptions#getAllLabels()}, and the implicit ones are those that
    * are returned from {@link Fragment#getImplicitLabels}.
    */
-  private void sanityCheck(Fragment fragment, BuildOptions buildOptions,
-      PackageProviderForConfigurations packageProvider) throws InvalidConfigurationException {
+  private static void sanityCheck(
+      Fragment fragment,
+      BuildOptions buildOptions,
+      PackageProviderForConfigurations packageProvider)
+      throws InvalidConfigurationException, InterruptedException {
     if (fragment == null) {
       return;
     }
@@ -134,8 +136,9 @@
     }
   }
 
-  private void collectAllTransitiveLabels(PackageProviderForConfigurations packageProvider,
-      Set<Label> reachableLabels, Label from) throws NoSuchThingException {
+  private static void collectAllTransitiveLabels(
+      PackageProviderForConfigurations packageProvider, Set<Label> reachableLabels, Label from)
+      throws NoSuchThingException, InterruptedException {
     if (!reachableLabels.add(from)) {
       return;
     }
@@ -189,12 +192,13 @@
     }
 
     @Override
-    public Target getTarget(Label label) throws NoSuchPackageException, NoSuchTargetException {
+    public Target getTarget(Label label)
+        throws NoSuchPackageException, NoSuchTargetException, InterruptedException {
       return packageProvider.getTarget(label);
     }
 
     @Override
-    public Path getPath(Package pkg, String fileName) {
+    public Path getPath(Package pkg, String fileName) throws InterruptedException {
       Path result = pkg.getPackageDirectory().getRelative(fileName);
       try {
         packageProvider.addDependency(pkg, fileName);
@@ -205,13 +209,13 @@
     }
 
     @Override
-    public <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType) 
-        throws InvalidConfigurationException {
+    public <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType)
+        throws InvalidConfigurationException, InterruptedException {
       return packageProvider.getFragment(buildOptions, fragmentType);
     }
 
     @Override
-    public BlazeDirectories getBlazeDirectories() {
+    public BlazeDirectories getBlazeDirectories() throws InterruptedException {
       return packageProvider.getDirectories();
     }
   }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
index 9a82ef4..0bd188a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -75,7 +75,6 @@
 import com.google.devtools.build.skyframe.SkyValue;
 import com.google.devtools.build.skyframe.ValueOrException;
 import com.google.devtools.build.skyframe.ValueOrException2;
-
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -84,7 +83,6 @@
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -416,15 +414,18 @@
    * transitive closure.
    *
    * <p>This method is heavily performance-optimized. Because it, in aggregate, reads over every
-   * edge in the configured target graph, small inefficiencies can have observable impact on
-   * build analysis time. Keep this in mind when making modifications and performance-test any
-   * changes you make.
+   * edge in the configured target graph, small inefficiencies can have observable impact on build
+   * analysis time. Keep this in mind when making modifications and performance-test any changes you
+   * make.
    */
   @Nullable
-  static OrderedSetMultimap<Attribute, Dependency> trimConfigurations(Environment env,
-      TargetAndConfiguration ctgValue, OrderedSetMultimap<Attribute, Dependency> originalDeps,
-      BuildConfiguration hostConfiguration, RuleClassProvider ruleClassProvider)
-      throws DependencyEvaluationException {
+  static OrderedSetMultimap<Attribute, Dependency> trimConfigurations(
+      Environment env,
+      TargetAndConfiguration ctgValue,
+      OrderedSetMultimap<Attribute, Dependency> originalDeps,
+      BuildConfiguration hostConfiguration,
+      RuleClassProvider ruleClassProvider)
+      throws DependencyEvaluationException, InterruptedException {
 
     // Maps each Skyframe-evaluated BuildConfiguration to the dependencies that need that
     // configuration. For cases where Skyframe isn't needed to get the configuration (e.g. when
@@ -684,7 +685,7 @@
       Map<SkyKey, ConfiguredTarget> configuredTargetMap,
       Iterable<Dependency> deps,
       NestedSetBuilder<Package> transitivePackages)
-      throws AspectCreationException {
+      throws AspectCreationException, InterruptedException {
     OrderedSetMultimap<SkyKey, ConfiguredAspect> result = OrderedSetMultimap.create();
     Set<SkyKey> aspectKeys = new HashSet<>();
     for (Dependency dep : deps) {
@@ -766,18 +767,21 @@
   }
 
   /**
-   * Returns the set of {@link ConfigMatchingProvider}s that key the configurable attributes
-   * used by this rule.
+   * Returns the set of {@link ConfigMatchingProvider}s that key the configurable attributes used by
+   * this rule.
    *
-   * <p>>If the configured targets supplying those providers aren't yet resolved by the
-   * dependency resolver, returns null.
+   * <p>>If the configured targets supplying those providers aren't yet resolved by the dependency
+   * resolver, returns null.
    */
   @Nullable
-  static ImmutableMap<Label, ConfigMatchingProvider> getConfigConditions(Target target,
-      Environment env, SkyframeDependencyResolver resolver, TargetAndConfiguration ctgValue,
+  static ImmutableMap<Label, ConfigMatchingProvider> getConfigConditions(
+      Target target,
+      Environment env,
+      SkyframeDependencyResolver resolver,
+      TargetAndConfiguration ctgValue,
       NestedSetBuilder<Package> transitivePackages,
       NestedSetBuilder<Label> transitiveLoadingRootCauses)
-      throws DependencyEvaluationException {
+      throws DependencyEvaluationException, InterruptedException {
     if (!(target instanceof Rule)) {
       return NO_CONFIG_CONDITIONS;
     }
@@ -847,15 +851,19 @@
     return ImmutableMap.copyOf(configConditions);
   }
 
-  /***
-   * Resolves the targets referenced in depValueNames and returns their ConfiguredTarget instances.
+  /**
+   * * Resolves the targets referenced in depValueNames and returns their ConfiguredTarget
+   * instances.
    *
    * <p>Returns null if not all instances are available yet.
    */
   @Nullable
   private static Map<SkyKey, ConfiguredTarget> resolveConfiguredTargetDependencies(
-      Environment env, Collection<Dependency> deps, NestedSetBuilder<Package> transitivePackages,
-      NestedSetBuilder<Label> transitiveLoadingRootCauses) throws DependencyEvaluationException {
+      Environment env,
+      Collection<Dependency> deps,
+      NestedSetBuilder<Package> transitivePackages,
+      NestedSetBuilder<Label> transitiveLoadingRootCauses)
+      throws DependencyEvaluationException, InterruptedException {
     boolean missedValues = env.valuesMissing();
     boolean failed = false;
     Iterable<SkyKey> depKeys = Iterables.transform(deps, TO_KEYS);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunction.java
index 09debbf..68c9ff8 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunction.java
@@ -18,7 +18,6 @@
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import javax.annotation.Nullable;
 
 /**
@@ -27,7 +26,7 @@
 public class ContainingPackageLookupFunction implements SkyFunction {
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) {
+  public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
     PackageIdentifier dir = (PackageIdentifier) skyKey.argument();
     PackageLookupValue pkgLookupValue =
         (PackageLookupValue) env.getValue(PackageLookupValue.key(dir));
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java
index 53d7a86..70de5cc 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java
@@ -30,7 +30,7 @@
   CoverageReportFunction() {}
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) {
+  public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
     Preconditions.checkState(
         CoverageReportValue.SKY_KEY.equals(skyKey), String.format(
             "Expected %s for SkyKey but got %s instead", CoverageReportValue.SKY_KEY, skyKey));
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingFunction.java
index 3c1401c..97ee8b7 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingFunction.java
@@ -18,7 +18,6 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import javax.annotation.Nullable;
 
 /**
@@ -28,7 +27,7 @@
 
   @Override
   public SkyValue compute(SkyKey skyKey, Environment env)
-      throws DirectoryListingFunctionException {
+      throws DirectoryListingFunctionException, InterruptedException {
     RootedPath dirRootedPath = (RootedPath) skyKey.argument();
 
     FileValue dirFileValue = (FileValue) env.getValue(FileValue.key(dirRootedPath));
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java
index 0bb5249..aa1fe76 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java
@@ -18,7 +18,6 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.io.IOException;
 
 /**
@@ -37,7 +36,7 @@
 
   @Override
   public SkyValue compute(SkyKey skyKey, Environment env)
-      throws DirectoryListingStateFunctionException {
+      throws DirectoryListingStateFunctionException, InterruptedException {
     RootedPath dirRootedPath = (RootedPath) skyKey.argument();
 
     try {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java
index 92888d2..96a65b5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java
@@ -36,7 +36,6 @@
 import com.google.devtools.build.lib.vfs.RootedPath;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
 import com.google.devtools.build.skyframe.SkyKey;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -56,7 +55,7 @@
 
   @Override
   public Package getPackage(EventHandler eventHandler, PackageIdentifier packageName)
-      throws NoSuchPackageException, MissingDepException {
+      throws NoSuchPackageException, MissingDepException, InterruptedException {
     SkyKey pkgKey = PackageValue.key(packageName);
     PackageValue pkgValue =
         (PackageValue) env.getValueOrThrow(pkgKey, NoSuchPackageException.class);
@@ -93,7 +92,7 @@
 
   @Override
   public boolean isPackage(EventHandler eventHandler, PackageIdentifier packageId)
-      throws MissingDepException {
+      throws MissingDepException, InterruptedException {
     SkyKey packageLookupKey = PackageLookupValue.key(packageId);
     try {
       PackageLookupValue packageLookupValue =
@@ -111,9 +110,10 @@
 
   @Override
   public Iterable<PathFragment> getPackagesUnderDirectory(
-      RepositoryName repository, PathFragment directory,
+      RepositoryName repository,
+      PathFragment directory,
       ImmutableSet<PathFragment> excludedSubdirectories)
-      throws MissingDepException {
+      throws MissingDepException, InterruptedException {
     PathPackageLocator packageLocator = PrecomputedValue.PATH_PACKAGE_LOCATOR.get(env);
     if (packageLocator == null) {
       throw new MissingDepException();
@@ -156,8 +156,9 @@
   }
 
   @Override
-  public Target getTarget(EventHandler eventHandler, Label label) throws NoSuchPackageException,
-      NoSuchTargetException, MissingDepException {
+  public Target getTarget(EventHandler eventHandler, Label label)
+      throws NoSuchPackageException, NoSuchTargetException, MissingDepException,
+          InterruptedException {
     return getPackage(eventHandler, label.getPackageIdentifier()).getTarget(label.getName());
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
index 792cc5f..b1b6259 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
@@ -23,7 +23,6 @@
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.RootedPath;
 import com.google.devtools.build.skyframe.SkyFunction;
-
 import java.io.IOException;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -82,12 +81,12 @@
      * external repository). Such files are theoretically mutable, but certain Blaze flags may tell
      * Blaze to assume these files are immutable.
      *
-     * Note that {@link ExternalFilesHelper#maybeHandleExternalFile} is only used for
-     * {@link FileStateValue} and {@link DirectoryStateValue}, and also note that output files do
-     * not normally have corresponding {@link FileValue} instances (and thus also
-     * {@link FileStateValue} instances) in the Skyframe graph ({@link ArtifactFunction} only uses
-     * {@link FileValue}s for source files). But {@link FileStateValue}s for output files can still
-     * make their way into the Skyframe graph if e.g. a source file is a symlink to an output file.
+     * <p>Note that {@link ExternalFilesHelper#maybeHandleExternalFile} is only used for {@link
+     * FileStateValue} and {@link DirectoryListingStateValue}, and also note that output files do
+     * not normally have corresponding {@link FileValue} instances (and thus also {@link
+     * FileStateValue} instances) in the Skyframe graph ({@link ArtifactFunction} only uses {@link
+     * FileValue}s for source files). But {@link FileStateValue}s for output files can still make
+     * their way into the Skyframe graph if e.g. a source file is a symlink to an output file.
      */
     // TODO(nharmata): Consider an alternative design where we have an OutputFileDiffAwareness. This
     // could work but would first require that we clean up all RootedPath usage.
@@ -157,8 +156,8 @@
    * ERROR_OUT, it will throw an error instead.
    */
   @ThreadSafe
-  public void maybeHandleExternalFile(RootedPath rootedPath, SkyFunction.Environment env)
-      throws IOException {
+  void maybeHandleExternalFile(RootedPath rootedPath, SkyFunction.Environment env)
+      throws IOException, InterruptedException {
     FileType fileType = getAndNoteFileType(rootedPath);
     if (fileType == FileType.INTERNAL) {
       return;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalPackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalPackageFunction.java
index 2e5cf26..8a7bdd9 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalPackageFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalPackageFunction.java
@@ -18,7 +18,6 @@
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import javax.annotation.Nullable;
 
 /**
@@ -31,7 +30,7 @@
 
   @Nullable
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) {
+  public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
     RootedPath workspacePath = (RootedPath) skyKey.argument();
     SkyKey key = WorkspaceFileValue.key(workspacePath);
     WorkspaceFileValue value = (WorkspaceFileValue) env.getValue(key);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java
index 6eb9621..8404f53 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java
@@ -28,12 +28,10 @@
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.TreeSet;
 import java.util.concurrent.atomic.AtomicReference;
-
 import javax.annotation.Nullable;
 
 /**
@@ -51,7 +49,8 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) throws FileFunctionException {
+  public SkyValue compute(SkyKey skyKey, Environment env)
+      throws FileFunctionException, InterruptedException {
     RootedPath rootedPath = (RootedPath) skyKey.argument();
     RootedPath realRootedPath = null;
     FileStateValue realFileStateValue = null;
@@ -132,9 +131,9 @@
    * {@code null} if there was a missing dep.
    */
   @Nullable
-  private Pair<RootedPath, FileStateValue> resolveFromAncestors(
+  private static Pair<RootedPath, FileStateValue> resolveFromAncestors(
       RootedPath rootedPath, Environment env)
-      throws FileFunctionException, FileOutsidePackageRootsException {
+      throws FileFunctionException, FileOutsidePackageRootsException, InterruptedException {
     PathFragment relativePath = rootedPath.getRelativePath();
     RootedPath realRootedPath = rootedPath;
     FileValue parentFileValue = null;
@@ -180,14 +179,17 @@
   }
 
   /**
-   * Returns the symlink target and file state of {@code rootedPath}'s symlink to
-   * {@code symlinkTarget}, accounting for ancestor symlinks, or {@code null} if there was a
-   * missing dep.
+   * Returns the symlink target and file state of {@code rootedPath}'s symlink to {@code
+   * symlinkTarget}, accounting for ancestor symlinks, or {@code null} if there was a missing dep.
    */
   @Nullable
-  private Pair<RootedPath, FileStateValue> getSymlinkTargetRootedPath(RootedPath rootedPath,
-      PathFragment symlinkTarget, TreeSet<Path> orderedSeenPaths,
-      Iterable<RootedPath> symlinkChain, Environment env) throws FileFunctionException {
+  private Pair<RootedPath, FileStateValue> getSymlinkTargetRootedPath(
+      RootedPath rootedPath,
+      PathFragment symlinkTarget,
+      TreeSet<Path> orderedSeenPaths,
+      Iterable<RootedPath> symlinkChain,
+      Environment env)
+      throws FileFunctionException, InterruptedException {
     RootedPath symlinkTargetRootedPath;
     if (symlinkTarget.isAbsolute()) {
       Path path = rootedPath.asPath().getFileSystem().getRootDirectory().getRelative(
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java
index d77f7e3..f2dfff8 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java
@@ -19,7 +19,6 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.io.IOException;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -41,7 +40,8 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) throws FileStateFunctionException {
+  public SkyValue compute(SkyKey skyKey, Environment env)
+      throws FileStateFunctionException, InterruptedException {
     RootedPath rootedPath = (RootedPath) skyKey.argument();
 
     try {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java
index 7777946..f95274c 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java
@@ -49,7 +49,8 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey key, Environment env) throws FilesetEntryFunctionException {
+  public SkyValue compute(SkyKey key, Environment env)
+      throws FilesetEntryFunctionException, InterruptedException {
     FilesetTraversalParams t = (FilesetTraversalParams) key.argument();
     Preconditions.checkState(
         t.getNestedTraversal().isPresent() != t.getDirectTraversal().isPresent(),
@@ -226,8 +227,9 @@
     return null;
   }
 
-  private RecursiveFilesystemTraversalValue traverse(Environment env, String errorInfo,
-      DirectTraversal traversal) throws MissingDepException {
+  private static RecursiveFilesystemTraversalValue traverse(
+      Environment env, String errorInfo, DirectTraversal traversal)
+      throws MissingDepException, InterruptedException {
     SkyKey depKey = RecursiveFilesystemTraversalValue.key(
         new RecursiveFilesystemTraversalValue.TraversalRequest(traversal.getRoot().asRootedPath(),
             traversal.isGenerated(), traversal.getPackageBoundaryMode(), traversal.isPackage(),
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java b/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java
index 6f78572..4b9263e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java
@@ -45,7 +45,6 @@
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
 import com.google.devtools.build.skyframe.WalkableGraph;
-
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
@@ -62,7 +61,6 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-
 import javax.annotation.Nullable;
 
 /**
@@ -123,9 +121,9 @@
         dirtinessChecker, /*checkMissingValues=*/true);
   }
 
-  private static interface ValueFetcher {
+  private interface ValueFetcher {
     @Nullable
-    SkyValue get(SkyKey key);
+    SkyValue get(SkyKey key) throws InterruptedException;
   }
 
   private static class WalkableGraphBackedValueFetcher implements ValueFetcher {
@@ -137,7 +135,7 @@
 
     @Override
     @Nullable
-    public SkyValue get(SkyKey key) {
+    public SkyValue get(SkyKey key) throws InterruptedException {
       return walkableGraph.exists(key) ? walkableGraph.getValue(key) : null;
     }
   }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java
index 0651831..ec3f7138 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java
@@ -31,10 +31,8 @@
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.Map;
 import java.util.regex.Pattern;
-
 import javax.annotation.Nullable;
 
 /**
@@ -54,7 +52,8 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) throws GlobFunctionException {
+  public SkyValue compute(SkyKey skyKey, Environment env)
+      throws GlobFunctionException, InterruptedException {
     GlobDescriptor glob = (GlobDescriptor) skyKey.argument();
 
     // Note that the glob's package is assumed to exist which implies that the package's BUILD file
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
index 26e5f1b..5499189 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
@@ -47,7 +47,6 @@
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
 import com.google.devtools.build.skyframe.WalkableGraph;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -79,7 +78,7 @@
 
   @Override
   public Package getPackage(EventHandler eventHandler, PackageIdentifier packageName)
-      throws NoSuchPackageException {
+      throws NoSuchPackageException, InterruptedException {
     SkyKey pkgKey = PackageValue.key(packageName);
 
     PackageValue pkgValue;
@@ -98,8 +97,9 @@
   }
 
   @Override
-  public Map<PackageIdentifier, Package> bulkGetPackages(EventHandler eventHandler,
-      Iterable<PackageIdentifier> pkgIds) throws NoSuchPackageException {
+  public Map<PackageIdentifier, Package> bulkGetPackages(
+      EventHandler eventHandler, Iterable<PackageIdentifier> pkgIds)
+      throws NoSuchPackageException, InterruptedException {
     Set<SkyKey> pkgKeys = ImmutableSet.copyOf(PackageValue.keys(pkgIds));
 
     ImmutableMap.Builder<PackageIdentifier, Package> pkgResults = ImmutableMap.builder();
@@ -133,7 +133,8 @@
 
 
   @Override
-  public boolean isPackage(EventHandler eventHandler, PackageIdentifier packageName) {
+  public boolean isPackage(EventHandler eventHandler, PackageIdentifier packageName)
+      throws InterruptedException {
     SkyKey packageLookupKey = PackageLookupValue.key(packageName);
     if (!graph.exists(packageLookupKey)) {
       // If the package lookup key does not exist in the graph, then it must not correspond to any
@@ -158,8 +159,10 @@
 
   @Override
   public Iterable<PathFragment> getPackagesUnderDirectory(
-      RepositoryName repository, PathFragment directory,
-      ImmutableSet<PathFragment> excludedSubdirectories) {
+      RepositoryName repository,
+      PathFragment directory,
+      ImmutableSet<PathFragment> excludedSubdirectories)
+      throws InterruptedException {
     PathFragment.checkAllPathsAreUnder(excludedSubdirectories, directory);
 
     // Check that this package is covered by at least one of our universe patterns.
@@ -208,7 +211,8 @@
   private void collectPackagesUnder(
       final RepositoryName repository,
       Set<TraversalInfo> traversals,
-      ImmutableList.Builder<PathFragment> builder) {
+      ImmutableList.Builder<PathFragment> builder)
+      throws InterruptedException {
     Map<TraversalInfo, SkyKey> traversalToKeyMap =
         Maps.asMap(
             traversals,
@@ -256,7 +260,7 @@
 
   @Override
   public Target getTarget(EventHandler eventHandler, Label label)
-      throws NoSuchPackageException, NoSuchTargetException {
+      throws NoSuchPackageException, NoSuchTargetException, InterruptedException {
     return getPackage(eventHandler, label.getPackageIdentifier()).getTarget(label.getName());
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageErrorFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageErrorFunction.java
index b277321..17ba9be 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageErrorFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageErrorFunction.java
@@ -24,7 +24,6 @@
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import javax.annotation.Nullable;
 
 /**
@@ -44,7 +43,8 @@
 
   @Nullable
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) throws PackageErrorFunctionException {
+  public SkyValue compute(SkyKey skyKey, Environment env)
+      throws PackageErrorFunctionException, InterruptedException {
     PackageIdentifier packageIdentifier = (PackageIdentifier) skyKey.argument();
     try {
       SkyKey packageKey = PackageValue.key(packageIdentifier);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
index 186232a..54edcf5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
@@ -172,17 +172,19 @@
   }
 
   /**
-   * Marks the given dependencies, and returns those already present. Ignores any exception
-   * thrown while building the dependency, except for filesystem inconsistencies.
+   * Marks the given dependencies, and returns those already present. Ignores any exception thrown
+   * while building the dependency, except for filesystem inconsistencies.
    *
    * <p>We need to mark dependencies implicitly used by the legacy package loading code, but we
    * don't care about any skyframe errors since the package knows whether it's in error or not.
    */
   private static Pair<? extends Map<PathFragment, PackageLookupValue>, Boolean>
-  getPackageLookupDepsAndPropagateInconsistentFilesystemExceptions(
-      PackageIdentifier packageIdentifier,
-      Iterable<SkyKey> depKeys, Environment env, boolean packageWasInError)
-          throws InternalInconsistentFilesystemException {
+      getPackageLookupDepsAndPropagateInconsistentFilesystemExceptions(
+          PackageIdentifier packageIdentifier,
+          Iterable<SkyKey> depKeys,
+          Environment env,
+          boolean packageWasInError)
+          throws InternalInconsistentFilesystemException, InterruptedException {
     Preconditions.checkState(
         Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.PACKAGE_LOOKUP)), depKeys);
     boolean packageShouldBeInError = packageWasInError;
@@ -216,7 +218,7 @@
       Environment env,
       boolean packageWasInError)
       throws InternalInconsistentFilesystemException, FileOutsidePackageRootsException,
-          SymlinkOutsidePackageRootsException {
+          SymlinkOutsidePackageRootsException, InterruptedException {
     Preconditions.checkState(
         Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.FILE)), depKeys);
     boolean packageShouldBeInError = packageWasInError;
@@ -249,7 +251,7 @@
       Environment env,
       boolean packageWasInError)
       throws InternalInconsistentFilesystemException, FileOutsidePackageRootsException,
-          SymlinkOutsidePackageRootsException {
+          SymlinkOutsidePackageRootsException, InterruptedException {
     Preconditions.checkState(
         Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.GLOB)), depKeys);
     boolean packageShouldBeInError = packageWasInError;
@@ -289,7 +291,7 @@
       PackageIdentifier packageIdentifier,
       boolean containsErrors)
       throws InternalInconsistentFilesystemException, FileOutsidePackageRootsException,
-          SymlinkOutsidePackageRootsException {
+          SymlinkOutsidePackageRootsException, InterruptedException {
     boolean packageShouldBeInError = containsErrors;
 
     // TODO(bazel-team): This means that many packages will have to be preprocessed twice. Ouch!
@@ -368,11 +370,12 @@
 
   /**
    * Adds a dependency on the WORKSPACE file, representing it as a special type of package.
+   *
    * @throws PackageFunctionException if there is an error computing the workspace file or adding
-   * its rules to the //external package.
+   *     its rules to the //external package.
    */
   private SkyValue getExternalPackage(Environment env, Path packageLookupPath)
-      throws PackageFunctionException {
+      throws PackageFunctionException, InterruptedException {
     RootedPath workspacePath = RootedPath.toRootedPath(
         packageLookupPath, Label.EXTERNAL_PACKAGE_FILE_NAME);
     SkyKey workspaceKey = ExternalPackageFunction.key(workspacePath);
@@ -567,7 +570,8 @@
     return new PackageValue(pkg);
   }
 
-  private FileValue getBuildFileValue(Environment env, RootedPath buildFileRootedPath) {
+  private static FileValue getBuildFileValue(Environment env, RootedPath buildFileRootedPath)
+      throws InterruptedException {
     FileValue buildFileValue;
     try {
       buildFileValue = (FileValue) env.getValueOrThrow(FileValue.key(buildFileRootedPath),
@@ -747,7 +751,7 @@
 
   private static void handleLabelsCrossingSubpackagesAndPropagateInconsistentFilesystemExceptions(
       Path pkgRoot, PackageIdentifier pkgId, Package.Builder pkgBuilder, Environment env)
-          throws InternalInconsistentFilesystemException {
+      throws InternalInconsistentFilesystemException, InterruptedException {
     Set<SkyKey> containingPkgLookupKeys = Sets.newHashSet();
     Map<Target, SkyKey> targetToKey = new HashMap<>();
     for (Target target : pkgBuilder.getTargets()) {
@@ -921,7 +925,7 @@
 
     @Override
     public Token runAsync(List<String> includes, List<String> excludes, boolean excludeDirs)
-        throws BadGlobException {
+        throws BadGlobException, InterruptedException {
       List<SkyKey> globKeys = new ArrayList<>(includes.size() + excludes.size());
       LinkedHashSet<SkyKey> includesKeys = Sets.newLinkedHashSetWithExpectedSize(includes.size());
       LinkedHashSet<SkyKey> excludesKeys = Sets.newLinkedHashSetWithExpectedSize(excludes.size());
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java
index 638f2ee..6e425e8 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java
@@ -47,7 +47,8 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) throws PackageLookupFunctionException {
+  public SkyValue compute(SkyKey skyKey, Environment env)
+      throws PackageLookupFunctionException, InterruptedException {
     PathPackageLocator pkgLocator = PrecomputedValue.PATH_PACKAGE_LOCATOR.get(env);
     PackageIdentifier packageKey = (PackageIdentifier) skyKey.argument();
     if (PackageFunction.isDefaultsPackage(packageKey)) {
@@ -94,9 +95,9 @@
   }
 
   @Nullable
-  private FileValue getFileValue(
+  private static FileValue getFileValue(
       RootedPath fileRootedPath, Environment env, PackageIdentifier packageIdentifier)
-      throws PackageLookupFunctionException {
+      throws PackageLookupFunctionException, InterruptedException {
     String basename = fileRootedPath.asPath().getBaseName();
     SkyKey fileSkyKey = FileValue.key(fileRootedPath);
     FileValue fileValue = null;
@@ -122,12 +123,12 @@
     return fileValue;
   }
 
-  private PackageLookupValue getPackageLookupValue(
+  private static PackageLookupValue getPackageLookupValue(
       Environment env,
       ImmutableList<Path> packagePathEntries,
       PackageIdentifier packageIdentifier,
       BuildFileName buildFileName)
-      throws PackageLookupFunctionException {
+      throws PackageLookupFunctionException, InterruptedException {
     // TODO(bazel-team): The following is O(n^2) on the number of elements on the package path due
     // to having restart the SkyFunction after every new dependency. However, if we try to batch
     // the missing value keys, more dependencies than necessary will be declared. This wart can be
@@ -147,9 +148,9 @@
     return PackageLookupValue.NO_BUILD_FILE_VALUE;
   }
 
-  private PackageLookupValue computeWorkspacePackageLookupValue(
+  private static PackageLookupValue computeWorkspacePackageLookupValue(
       Environment env, ImmutableList<Path> packagePathEntries)
-      throws PackageLookupFunctionException {
+      throws PackageLookupFunctionException, InterruptedException {
     PackageLookupValue result =
         getPackageLookupValue(
             env, packagePathEntries, Label.EXTERNAL_PACKAGE_IDENTIFIER, BuildFileName.WORKSPACE);
@@ -182,11 +183,11 @@
    * Gets a PackageLookupValue from a different Bazel repository.
    *
    * <p>To do this, it looks up the "external" package and finds a path mapping for the repository
-   * name.</p>
+   * name.
    */
-  private PackageLookupValue computeExternalPackageLookupValue(
+  private static PackageLookupValue computeExternalPackageLookupValue(
       SkyKey skyKey, Environment env, PackageIdentifier packageIdentifier)
-      throws PackageLookupFunctionException {
+      throws PackageLookupFunctionException, InterruptedException {
     PackageIdentifier id = (PackageIdentifier) skyKey.argument();
     SkyKey repositoryKey = RepositoryValue.key(id.getRepository());
     RepositoryValue repositoryValue;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java
index e221ae7..08eecd7 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java
@@ -38,12 +38,10 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -134,8 +132,8 @@
    * target, or null if not all dependencies have yet been SkyFrame-evaluated.
    */
   @Nullable
-  private ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeConditions(
-      TargetAndConfiguration ctg, Environment env) {
+  private static ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeConditions(
+      TargetAndConfiguration ctg, Environment env) throws InterruptedException {
     if (!(ctg.getTarget() instanceof Rule)) {
       return ImmutableMap.of();
     }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
index a5f7a67..bc9977e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
@@ -32,10 +32,8 @@
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.Map;
 import java.util.UUID;
-
 import javax.annotation.Nullable;
 
 /**
@@ -138,7 +136,7 @@
     return "<BuildVariable " + value + ">";
   }
 
-  public static final void dependOnBuildId(SkyFunction.Environment env) {
+  public static void dependOnBuildId(SkyFunction.Environment env) throws InterruptedException {
     BUILD_ID.get(env);
   }
 
@@ -166,7 +164,7 @@
      */
     @Nullable
     @SuppressWarnings("unchecked")
-    public T get(SkyFunction.Environment env) {
+    public T get(SkyFunction.Environment env) throws InterruptedException {
       PrecomputedValue value = (PrecomputedValue) env.getValue(key);
       if (value == null) {
         return null;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java
index 7524bee..fc9cd81 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java
@@ -44,11 +44,9 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
-
 import javax.annotation.Nullable;
 
 /**
@@ -177,16 +175,17 @@
     }
 
     @Override
-    public ResolvedTargets<Void> getTargetsInPackage(String originalPattern,
-        PackageIdentifier packageIdentifier, boolean rulesOnly) throws TargetParsingException {
+    public ResolvedTargets<Void> getTargetsInPackage(
+        String originalPattern, PackageIdentifier packageIdentifier, boolean rulesOnly)
+        throws TargetParsingException, InterruptedException {
       FilteringPolicy policy =
           rulesOnly ? FilteringPolicies.RULES_ONLY : FilteringPolicies.NO_FILTER;
       return getTargetsInPackage(originalPattern, packageIdentifier, policy);
     }
 
-    private ResolvedTargets<Void> getTargetsInPackage(String originalPattern,
-        PackageIdentifier packageIdentifier, FilteringPolicy policy)
-        throws TargetParsingException {
+    private ResolvedTargets<Void> getTargetsInPackage(
+        String originalPattern, PackageIdentifier packageIdentifier, FilteringPolicy policy)
+        throws TargetParsingException, InterruptedException {
       try {
         Package pkg = packageProvider.getPackage(env.getListener(), packageIdentifier);
         ResolvedTargets<Target> packageTargets =
@@ -209,7 +208,7 @@
     }
 
     @Override
-    public boolean isPackage(PackageIdentifier packageIdentifier) {
+    public boolean isPackage(PackageIdentifier packageIdentifier) throws InterruptedException {
       return packageProvider.isPackage(env.getListener(), packageIdentifier);
     }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java
index b5b560a..568b623 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java
@@ -32,9 +32,7 @@
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -50,7 +48,7 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) {
+  public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
     PrepareDepsOfTargetsUnderDirectoryKey argument =
         (PrepareDepsOfTargetsUnderDirectoryKey) skyKey.argument();
     FilteringPolicy filteringPolicy = argument.getFilteringPolicy();
@@ -102,13 +100,13 @@
     }
 
     @Override
-    public void visitPackageValue(Package pkg, Environment env) {
+    public void visitPackageValue(Package pkg, Environment env) throws InterruptedException {
       loadTransitiveTargets(env, pkg, filteringPolicy);
     }
   }
 
   private static void loadTransitiveTargets(
-      Environment env, Package pkg, FilteringPolicy filteringPolicy) {
+      Environment env, Package pkg, FilteringPolicy filteringPolicy) throws InterruptedException {
     ResolvedTargets<Target> packageTargets =
         TargetPatternResolverUtil.resolvePackageTargets(pkg, filteringPolicy);
     ImmutableList.Builder<SkyKey> builder = ImmutableList.builder();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java
index 24696d0..4c66e8f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java
@@ -39,7 +39,6 @@
 import com.google.devtools.build.skyframe.SkyValue;
 import com.google.devtools.build.skyframe.ValueOrException;
 import com.google.devtools.build.skyframe.ValueOrException4;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -105,25 +104,26 @@
   interface Visitor {
 
     /**
-     * Called iff the directory contains a package. Provides an {@link Environment} {@code env}
-     * so that the visitor may do additional lookups. {@link Environment#valuesMissing} will be
-     * checked afterwards.
+     * Called iff the directory contains a package. Provides an {@link Environment} {@code env} so
+     * that the visitor may do additional lookups. {@link Environment#valuesMissing} will be checked
+     * afterwards.
      */
-    void visitPackageValue(Package pkg, Environment env);
+    void visitPackageValue(Package pkg, Environment env) throws InterruptedException;
   }
 
   /**
-   * Looks in the directory specified by {@code recursivePkgKey} for a package, does some work
-   * as specified by {@link Visitor} if such a package exists, then recursively does work in each
+   * Looks in the directory specified by {@code recursivePkgKey} for a package, does some work as
+   * specified by {@link Visitor} if such a package exists, then recursively does work in each
    * non-excluded subdirectory as specified by {@link #getSkyKeyForSubdirectory}, and finally
-   * aggregates the {@link Visitor} value along with values from each subdirectory as specified
-   * by {@link #aggregateWithSubdirectorySkyValues}, and returns that aggregation.
+   * aggregates the {@link Visitor} value along with values from each subdirectory as specified by
+   * {@link #aggregateWithSubdirectorySkyValues}, and returns that aggregation.
    *
    * <p>Returns null if {@code env.valuesMissing()} is true, checked after each call to one of
    * {@link RecursiveDirectoryTraversalFunction}'s abstract methods that were given {@code env}.
    * (And after each of {@code visitDirectory}'s own uses of {@code env}, of course.)
    */
-  TReturn visitDirectory(RecursivePkgKey recursivePkgKey, Environment env) {
+  TReturn visitDirectory(RecursivePkgKey recursivePkgKey, Environment env)
+      throws InterruptedException {
     RootedPath rootedPath = recursivePkgKey.getRootedPath();
     ImmutableSet<PathFragment> excludedPaths = recursivePkgKey.getExcludedPaths();
     Path root = rootedPath.getRoot();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
index b7f7b92..e122307 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
@@ -31,12 +31,10 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /** A {@link SkyFunction} to build {@link RecursiveFilesystemTraversalValue}s. */
@@ -109,7 +107,7 @@
 
   @Override
   public SkyValue compute(SkyKey skyKey, Environment env)
-      throws RecursiveFilesystemTraversalFunctionException {
+      throws RecursiveFilesystemTraversalFunctionException, InterruptedException {
     TraversalRequest traversal = (TraversalRequest) skyKey.argument();
     try {
       // Stat the traversal root.
@@ -204,7 +202,7 @@
   }
 
   private static FileInfo lookUpFileInfo(Environment env, TraversalRequest traversal)
-      throws MissingDepException {
+      throws MissingDepException, InterruptedException {
     // Stat the file.
     FileValue fileValue = (FileValue) getDependentSkyValue(env, FileValue.key(traversal.path));
     if (fileValue.exists()) {
@@ -279,8 +277,9 @@
    *     {@link FileInfo} so the caller should use these instead of the old ones (this happens when
    *     a package is found, but under a different root than expected)
    */
-  private static PkgLookupResult checkIfPackage(Environment env, TraversalRequest traversal,
-      FileInfo rootInfo) throws MissingDepException {
+  private static PkgLookupResult checkIfPackage(
+      Environment env, TraversalRequest traversal, FileInfo rootInfo)
+      throws MissingDepException, InterruptedException {
     Preconditions.checkArgument(rootInfo.type.exists() && !rootInfo.type.isFile(),
         "{%s} {%s}", traversal, rootInfo);
     PackageLookupValue pkgLookup = (PackageLookupValue) getDependentSkyValue(env,
@@ -315,8 +314,9 @@
    *
    * <p>The returned keys are of type {@link SkyFunctions#RECURSIVE_FILESYSTEM_TRAVERSAL}.
    */
-  private static Collection<SkyKey> createRecursiveTraversalKeys(Environment env,
-      TraversalRequest traversal) throws MissingDepException {
+  private static Collection<SkyKey> createRecursiveTraversalKeys(
+      Environment env, TraversalRequest traversal)
+      throws MissingDepException, InterruptedException {
     // Use the traversal's path, even if it's a symlink. The contents of the directory, as listed
     // in the result, must be relative to it.
     DirectoryListingValue dirListing = (DirectoryListingValue) getDependentSkyValue(env,
@@ -405,7 +405,7 @@
   }
 
   private static SkyValue getDependentSkyValue(Environment env, SkyKey key)
-      throws MissingDepException {
+      throws MissingDepException, InterruptedException {
     SkyValue value = env.getValue(key);
     if (env.valuesMissing()) {
       throw new MissingDepException();
@@ -419,8 +419,7 @@
    * <p>The keys must all be {@link SkyFunctions#RECURSIVE_FILESYSTEM_TRAVERSAL} keys.
    */
   private static Collection<RecursiveFilesystemTraversalValue> traverseChildren(
-      Environment env, Iterable<SkyKey> keys)
-      throws MissingDepException {
+      Environment env, Iterable<SkyKey> keys) throws MissingDepException, InterruptedException {
     Map<SkyKey, SkyValue> values = env.getValues(keys);
     if (env.valuesMissing()) {
       throw new MissingDepException();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java
index 642d8ea..a01a1f4 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java
@@ -44,7 +44,6 @@
 import com.google.devtools.build.lib.pkgcache.TargetPatternResolverUtil;
 import com.google.devtools.build.lib.util.BatchCallback;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -171,7 +170,7 @@
   }
 
   @Override
-  public boolean isPackage(PackageIdentifier packageIdentifier) {
+  public boolean isPackage(PackageIdentifier packageIdentifier) throws InterruptedException {
     return recursivePackageProvider.isPackage(eventHandler, packageIdentifier);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java
index 607e9b2..9b97b4b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java
@@ -27,9 +27,7 @@
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -48,7 +46,7 @@
 
   /** N.B.: May silently throw {@link NoSuchPackageException} in nokeep_going mode! */
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) {
+  public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
     return new MyTraversalFunction().visitDirectory((RecursivePkgKey) skyKey.argument(), env);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
index b5c0863..11d6600 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
@@ -74,7 +74,6 @@
 import com.google.devtools.build.lib.vfs.Symlinks;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
 import com.google.protobuf.ByteString;
-
 import java.io.IOException;
 import java.util.Collection;
 import java.util.HashSet;
@@ -92,7 +91,6 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.atomic.AtomicReference;
-
 import javax.annotation.Nullable;
 
 /**
@@ -503,7 +501,7 @@
 
   @Nullable
   Iterable<Artifact> getActionCachedInputs(Action action, PackageRootResolver resolver)
-      throws PackageRootResolutionException {
+      throws PackageRootResolutionException, InterruptedException {
     return actionCacheChecker.getCachedInputs(action, resolver);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAwareAction.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAwareAction.java
index 6c2caf1..43c0193 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAwareAction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAwareAction.java
@@ -40,7 +40,7 @@
 public interface SkyframeAwareAction {
 
   /** Wrapper and/or base class for exceptions raised in {@link #establishSkyframeDependencies}. */
-  public static class ExceptionBase extends Exception {
+  class ExceptionBase extends Exception {
     public ExceptionBase(String message) {
       super(message);
     }
@@ -53,11 +53,11 @@
   /**
    * Establish dependencies on Skyframe values before executing the action.
    *
-   * <p><b>IMPORTANT</b>: actions that implement this interface should override
-   * {@code Action.executeUnconditionally} and return true. See {@link SkyframeAwareAction} why.
+   * <p><b>IMPORTANT</b>: actions that implement this interface should override {@code
+   * Action.executeUnconditionally} and return true. See {@link SkyframeAwareAction} why.
    *
-   * <p>This method should perform as little computation as possible: ideally it should request
-   * one or a few SkyValues, perhaps set some state somewhere and return. If this method needs to
+   * <p>This method should perform as little computation as possible: ideally it should request one
+   * or a few SkyValues, perhaps set some state somewhere and return. If this method needs to
    * perform anything more complicated than that, including perhaps some non-trivial computation,
    * you should implement that as a SkyFunction and request the corresponding SkyValue in this
    * method.
@@ -69,5 +69,5 @@
    * exceptions); that is the responsibility of the caller. It should return as soon as possible,
    * ready to be called again at a later time if need be.
    */
-  void establishSkyframeDependencies(Environment env) throws ExceptionBase;
+  void establishSkyframeDependencies(Environment env) throws ExceptionBase, InterruptedException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
index 546a0e2..2d80c52 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
@@ -73,13 +73,11 @@
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.logging.Logger;
-
 import javax.annotation.Nullable;
 
 /**
@@ -430,7 +428,8 @@
    */
   // TODO(bazel-team): Allow analysis to return null so the value builder can exit and wait for a
   // restart deps are not present.
-  private boolean getWorkspaceStatusValues(Environment env, BuildConfiguration config) {
+  private static boolean getWorkspaceStatusValues(Environment env, BuildConfiguration config)
+      throws InterruptedException {
     env.getValue(WorkspaceStatusValue.SKY_KEY);
     Map<BuildInfoKey, BuildInfoFactory> buildInfoFactories =
         PrecomputedValue.BUILD_INFO_FACTORIES.get(env);
@@ -451,9 +450,13 @@
 
   /** Returns null if any build-info values are not ready. */
   @Nullable
-  CachingAnalysisEnvironment createAnalysisEnvironment(ArtifactOwner owner,
-      boolean isSystemEnv, EventHandler eventHandler,
-      Environment env, BuildConfiguration config) {
+  CachingAnalysisEnvironment createAnalysisEnvironment(
+      ArtifactOwner owner,
+      boolean isSystemEnv,
+      EventHandler eventHandler,
+      Environment env,
+      BuildConfiguration config)
+      throws InterruptedException {
     if (config != null && !getWorkspaceStatusValues(env, config)) {
       return null;
     }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java
index 09fc0f2..965c3fb 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java
@@ -31,12 +31,10 @@
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.ValueOrException;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -65,7 +63,8 @@
   }
 
   @Override
-  protected void missingEdgeHook(Target from, Label to, NoSuchThingException e) {
+  protected void missingEdgeHook(Target from, Label to, NoSuchThingException e)
+      throws InterruptedException {
     if (e instanceof NoSuchTargetException) {
       NoSuchTargetException nste = (NoSuchTargetException) e;
       if (to.equals(nste.getLabel())) {
@@ -87,7 +86,8 @@
 
   @Nullable
   @Override
-  protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses) {
+  protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses)
+      throws InterruptedException {
     SkyKey key = PackageValue.key(label.getPackageIdentifier());
     PackageValue packageValue;
     try {
@@ -125,7 +125,8 @@
   @Override
   protected List<BuildConfiguration> getConfigurations(
       Set<Class<? extends BuildConfiguration.Fragment>> fragments,
-      Iterable<BuildOptions> buildOptions) throws InvalidConfigurationException {
+      Iterable<BuildOptions> buildOptions)
+      throws InvalidConfigurationException, InterruptedException {
     List<SkyKey> keys = new ArrayList<>();
     for (BuildOptions options : buildOptions) {
       keys.add(BuildConfigurationValue.key(fragments, options));
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframePackageLoaderWithValueEnvironment.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframePackageLoaderWithValueEnvironment.java
index 7ebb7b0..ceda171 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframePackageLoaderWithValueEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframePackageLoaderWithValueEnvironment.java
@@ -32,7 +32,6 @@
 import com.google.devtools.build.skyframe.MemoizingEvaluator;
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyKey;
-
 import java.io.IOException;
 
 /**
@@ -56,7 +55,7 @@
   }
 
   private Package getPackage(final PackageIdentifier pkgIdentifier)
-      throws NoSuchPackageException {
+      throws NoSuchPackageException, InterruptedException {
     SkyKey key = PackageValue.key(pkgIdentifier);
     PackageValue value = (PackageValue) env.getValueOrThrow(key, NoSuchPackageException.class);
     if (value != null) {
@@ -66,13 +65,15 @@
   }
 
   @Override
-  public Target getTarget(Label label) throws NoSuchPackageException, NoSuchTargetException {
+  public Target getTarget(Label label)
+      throws NoSuchPackageException, NoSuchTargetException, InterruptedException {
     Package pkg = getPackage(label.getPackageIdentifier());
     return pkg == null ? null : pkg.getTarget(label.getName());
   }
 
   @Override
-  public void addDependency(Package pkg, String fileName) throws LabelSyntaxException, IOException {
+  public void addDependency(Package pkg, String fileName)
+      throws LabelSyntaxException, IOException, InterruptedException {
     RootedPath fileRootedPath = RootedPath.toRootedPath(pkg.getSourceRoot(),
         pkg.getPackageIdentifier().getSourceRoot().getRelative(fileName));
     FileValue result = (FileValue) env.getValue(FileValue.key(fileRootedPath));
@@ -83,7 +84,7 @@
 
   @Override
   public <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType)
-      throws InvalidConfigurationException {
+      throws InvalidConfigurationException, InterruptedException {
     ConfigurationFragmentValue fragmentNode = (ConfigurationFragmentValue) env.getValueOrThrow(
         ConfigurationFragmentValue.key(buildOptions, fragmentType, ruleClassProvider),
         InvalidConfigurationException.class);
@@ -94,7 +95,7 @@
   }
 
   @Override
-  public BlazeDirectories getDirectories() {
+  public BlazeDirectories getDirectories() throws InterruptedException {
     return PrecomputedValue.BLAZE_DIRECTORIES.get(env);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
index c4889fa..951d8a7 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
@@ -47,13 +47,11 @@
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
 import com.google.devtools.build.skyframe.ValueOrException2;
-
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -211,17 +209,17 @@
   }
 
   /**
-   * Computes the set of Labels corresponding to a collection of PathFragments representing
-   * absolute import paths.
-   * 
+   * Computes the set of Labels corresponding to a collection of PathFragments representing absolute
+   * import paths.
+   *
    * @return a map from the computed {@link Label}s to the corresponding {@link PathFragment}s;
-   *   {@code null} if any Skyframe dependencies are unavailable.
+   *     {@code null} if any Skyframe dependencies are unavailable.
    * @throws SkylarkImportFailedException
    */
   @Nullable
   static ImmutableMap<PathFragment, Label> labelsForAbsoluteImports(
       ImmutableSet<PathFragment> pathsToLookup, Environment env)
-          throws SkylarkImportFailedException {
+      throws SkylarkImportFailedException, InterruptedException {
 
     // Import PathFragments are absolute, so there is a 1-1 mapping from corresponding Labels.
     ImmutableMap.Builder<PathFragment, Label> outputMap = new ImmutableMap.Builder<>();
@@ -290,19 +288,17 @@
 
   /**
    * Computes the set of {@link Label}s corresponding to a set of Skylark {@link LoadStatement}s.
-   * 
+   *
    * @param imports a collection of Skylark {@link LoadStatement}s
    * @param containingFileLabel the {@link Label} of the file containing the load statements
-   * @return an {@link ImmutableMap} which maps a {@link String} used in the load statement to
-   *     its corresponding {@Label}. Returns {@code null} if any Skyframe dependencies are
-   *     unavailable.
-   * @throws SkylarkImportFailedException if no package can be found that contains the
-   *     loaded file
+   * @return an {@link ImmutableMap} which maps a {@link String} used in the load statement to its
+   *     corresponding {@Label}. Returns {@code null} if any Skyframe dependencies are unavailable.
+   * @throws SkylarkImportFailedException if no package can be found that contains the loaded file
    */
   @Nullable
   static ImmutableMap<String, Label> findLabelsForLoadStatements(
       ImmutableCollection<SkylarkImport> imports, Label containingFileLabel, Environment env)
-          throws SkylarkImportFailedException {
+      throws SkylarkImportFailedException, InterruptedException {
     Preconditions.checkArgument(
         !containingFileLabel.getPackageIdentifier().getRepository().isDefault());
     Map<String, Label> outputMap = Maps.newHashMapWithExpectedSize(imports.size());
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunction.java
index 736455b..2aeba41 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunction.java
@@ -25,7 +25,6 @@
 import com.google.devtools.build.skyframe.SkyFunctionException;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import javax.annotation.Nullable;
 
 /**
@@ -37,7 +36,8 @@
 public final class TargetMarkerFunction implements SkyFunction {
 
   @Override
-  public SkyValue compute(SkyKey key, Environment env) throws TargetMarkerFunctionException {
+  public SkyValue compute(SkyKey key, Environment env)
+      throws TargetMarkerFunctionException, InterruptedException {
     try {
       return computeTargetMarkerValue(key, env);
     } catch (NoSuchTargetException e) {
@@ -50,7 +50,7 @@
 
   @Nullable
   static TargetMarkerValue computeTargetMarkerValue(SkyKey key, Environment env)
-      throws NoSuchTargetException, NoSuchPackageException {
+      throws NoSuchTargetException, NoSuchPackageException, InterruptedException {
     Label label = (Label) key.argument();
     PathFragment pkgForLabel = label.getPackageFragment();
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java
index 5215b73..60600ca 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java
@@ -53,7 +53,7 @@
 final class TargetPatternPhaseFunction implements SkyFunction {
 
   @Override
-  public TargetPatternPhaseValue compute(SkyKey key, Environment env) {
+  public TargetPatternPhaseValue compute(SkyKey key, Environment env) throws InterruptedException {
     TargetPatternList options = (TargetPatternList) key.argument();
     PackageValue packageValue = null;
     boolean workspaceError = false;
@@ -189,8 +189,9 @@
    * @param compileOneDependency if true, enables alternative interpretation of targetPatterns; see
    *     {@link LoadingOptions#compileOneDependency}
    */
-  private static ResolvedTargets<Target> getTargetsToBuild(Environment env,
-      List<String> targetPatterns, String offset, boolean compileOneDependency) {
+  private static ResolvedTargets<Target> getTargetsToBuild(
+      Environment env, List<String> targetPatterns, String offset, boolean compileOneDependency)
+      throws InterruptedException {
     List<SkyKey> patternSkyKeys = new ArrayList<>();
     for (TargetPatternSkyKeyOrException keyOrException :
         TargetPatternValue.keys(targetPatterns, FilteringPolicies.FILTER_MANUAL, offset)) {
@@ -253,8 +254,9 @@
    * @param targetPatterns the list of command-line target patterns specified by the user
    * @param testFilter the test filter
    */
-  private static ResolvedTargets<Target> determineTests(Environment env,
-      List<String> targetPatterns, String offset, TestFilter testFilter) {
+  private static ResolvedTargets<Target> determineTests(
+      Environment env, List<String> targetPatterns, String offset, TestFilter testFilter)
+      throws InterruptedException {
     List<SkyKey> patternSkyKeys = new ArrayList<>();
     for (TargetPatternSkyKeyOrException keyOrException :
         TargetPatternValue.keys(targetPatterns, FilteringPolicies.FILTER_TESTS, offset)) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java
index 7641f6e..e555b7d 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java
@@ -13,8 +13,6 @@
 // limitations under the License.
 package com.google.devtools.build.lib.skyframe;
 
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -32,9 +30,9 @@
 import com.google.devtools.build.lib.pkgcache.FilteringPolicy;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.skyframe.InterruptibleSupplier;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -209,13 +207,15 @@
       return excludedSubdirectories;
     }
 
-    public ImmutableSet<PathFragment> getAllSubdirectoriesToExclude(
-        Iterable<PathFragment> blacklistedPackagePrefixes) {
-      return getAllSubdirectoriesToExclude(Suppliers.ofInstance(blacklistedPackagePrefixes));
+    ImmutableSet<PathFragment> getAllSubdirectoriesToExclude(
+        Iterable<PathFragment> blacklistedPackagePrefixes) throws InterruptedException {
+      return getAllSubdirectoriesToExclude(
+          new InterruptibleSupplier.Instance<>(blacklistedPackagePrefixes));
     }
 
     public ImmutableSet<PathFragment> getAllSubdirectoriesToExclude(
-        Supplier<? extends Iterable<PathFragment>> blacklistedPackagePrefixes) {
+        InterruptibleSupplier<? extends Iterable<PathFragment>> blacklistedPackagePrefixes)
+        throws InterruptedException {
       ImmutableSet.Builder<PathFragment> excludedPathsBuilder = ImmutableSet.builder();
       excludedPathsBuilder.addAll(getExcludedSubdirectories());
       if (parsedPattern.getType() == Type.TARGETS_BELOW_DIRECTORY) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternsResultBuilder.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternsResultBuilder.java
index 575a0ff..3d0acf0 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternsResultBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternsResultBuilder.java
@@ -23,7 +23,6 @@
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.skyframe.WalkableGraph;
-
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -43,10 +42,9 @@
     hasError = true;
   }
 
-  /**
-   * Returns final set of targets and sets error flag if required.
-   */
-  public ResolvedTargets<Target> build(WalkableGraph walkableGraph) throws TargetParsingException {
+  /** Returns final set of targets and sets error flag if required. */
+  public ResolvedTargets<Target> build(WalkableGraph walkableGraph)
+      throws TargetParsingException, InterruptedException {
     precomputePackages(walkableGraph);
     ResolvedTargets.Builder<Target> resolvedTargetsBuilder = buildInternal();
     if (hasError) {
@@ -74,7 +72,7 @@
     return resolvedTargetsBuilder;
   }
 
-  private void precomputePackages(WalkableGraph walkableGraph) {
+  private void precomputePackages(WalkableGraph walkableGraph) throws InterruptedException {
     Set<PackageIdentifier> packagesToRequest = getPackagesIdentifiers();      
     packages = Maps.newHashMapWithExpectedSize(packagesToRequest.size());
     for (PackageIdentifier pkgIdentifier : packagesToRequest) {
@@ -102,8 +100,8 @@
     return packagesIdentifiers;
   }
 
-  private Package findPackageInGraph(PackageIdentifier pkgIdentifier,
-      WalkableGraph walkableGraph) {
+  private static Package findPackageInGraph(
+      PackageIdentifier pkgIdentifier, WalkableGraph walkableGraph) throws InterruptedException {
     return Preconditions.checkNotNull(
             ((PackageValue) walkableGraph.getValue(PackageValue.key(pkgIdentifier))), pkgIdentifier)
         .getPackage();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionFunction.java
index d277b19..3523d33 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionFunction.java
@@ -29,12 +29,8 @@
  * runs.
  */
 public final class TestCompletionFunction implements SkyFunction {
-
-  public TestCompletionFunction() {
-  }
-
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) {
+  public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
     TestCompletionValue.TestCompletionKey key =
         (TestCompletionValue.TestCompletionKey) skyKey.argument();
     LabelAndConfiguration lac = key.labelAndConfiguration();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TestSuiteExpansionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TestSuiteExpansionFunction.java
index d5ecb25..6324b2e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TestSuiteExpansionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TestSuiteExpansionFunction.java
@@ -25,7 +25,6 @@
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
@@ -33,7 +32,6 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -41,7 +39,7 @@
  */
 final class TestSuiteExpansionFunction implements SkyFunction {
   @Override
-  public SkyValue compute(SkyKey key, Environment env) {
+  public SkyValue compute(SkyKey key, Environment env) throws InterruptedException {
     TestSuiteExpansion expansion = (TestSuiteExpansion) key.argument();
     ResolvedTargets<Target> targets = labelsToTargets(env, expansion.getTargets(), false);
     List<SkyKey> testsInSuitesKeys = new ArrayList<>();
@@ -80,7 +78,7 @@
   }
 
   static ResolvedTargets<Target> labelsToTargets(
-      Environment env, ImmutableSet<Label> labels, boolean hasError) {
+      Environment env, ImmutableSet<Label> labels, boolean hasError) throws InterruptedException {
     Set<PackageIdentifier> pkgIdentifiers = new LinkedHashSet<>();
     for (Label label : labels) {
       pkgIdentifiers.add(label.getPackageIdentifier());
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TestsInSuiteFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TestsInSuiteFunction.java
index 4556c76..18a747e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TestsInSuiteFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TestsInSuiteFunction.java
@@ -35,7 +35,6 @@
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
 import com.google.devtools.build.skyframe.ValueOrException;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -44,7 +43,6 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -54,7 +52,7 @@
 // TODO(ulfjack): What about test_suite rules that include each other.
 final class TestsInSuiteFunction implements SkyFunction {
   @Override
-  public SkyValue compute(SkyKey key, Environment env) {
+  public SkyValue compute(SkyKey key, Environment env) throws InterruptedException {
     TestsInSuite expansion = (TestsInSuite) key.argument();
     ResolvedTargets<Target> result =
         computeTestsInSuite(env, expansion.getTestSuite(), expansion.isStrict());
@@ -65,13 +63,13 @@
   }
 
   /**
-   * Populates 'result' with all the tests associated with the specified
-   * 'testSuite'.  Throws an exception if any target is missing.
+   * Populates 'result' with all the tests associated with the specified 'testSuite'. Throws an
+   * exception if any target is missing.
    *
-   * <p>CAUTION!  Keep this logic consistent with {@code TestSuite}!
+   * <p>CAUTION! Keep this logic consistent with {@code TestSuite}!
    */
-  private ResolvedTargets<Target> computeTestsInSuite(
-      Environment env, Rule testSuite, boolean strict) {
+  private static ResolvedTargets<Target> computeTestsInSuite(
+      Environment env, Rule testSuite, boolean strict) throws InterruptedException {
     ResolvedTargets.Builder<Target> builder = ResolvedTargets.builder();
     List<Target> testsAndSuites = new ArrayList<>();
     // Note that testsAndSuites can contain input file targets; the test_suite rule does not
@@ -132,8 +130,9 @@
    * found a problem during the lookup process; the actual error message is reported to the
    * environment.
    */
-  private boolean getPrerequisites(Environment env, Rule testSuite, String attrName,
-      List<Target> targets) {
+  private static boolean getPrerequisites(
+      Environment env, Rule testSuite, String attrName, List<Target> targets)
+      throws InterruptedException {
     List<Label> labels =
         NonconfigurableAttributeMapper.of(testSuite).get(attrName, BuildType.LABEL_LIST);
     Set<PackageIdentifier> pkgIdentifiers = new LinkedHashSet<>();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java
index 44b161b..3bc1f30 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java
@@ -34,7 +34,6 @@
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
 import com.google.devtools.build.skyframe.ValueOrException2;
-
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -42,7 +41,6 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -79,10 +77,13 @@
 
   abstract TProcessedTargets processTarget(Label label, TargetAndErrorIfAny targetAndErrorIfAny);
 
-  abstract void processDeps(TProcessedTargets processedTargets, EventHandler eventHandler,
+  abstract void processDeps(
+      TProcessedTargets processedTargets,
+      EventHandler eventHandler,
       TargetAndErrorIfAny targetAndErrorIfAny,
       Iterable<Entry<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>>>
-          depEntries);
+          depEntries)
+      throws InterruptedException;
 
   /**
    * Returns a {@link SkyValue} based on the target and any errors it has, and the values
@@ -97,11 +98,11 @@
    */
   @Nullable
   abstract TargetMarkerValue getTargetMarkerValue(SkyKey targetMarkerKey, Environment env)
-      throws NoSuchTargetException, NoSuchPackageException;
+      throws NoSuchTargetException, NoSuchPackageException, InterruptedException;
 
   @Override
   public SkyValue compute(SkyKey key, Environment env)
-      throws TransitiveBaseTraversalFunctionException {
+      throws TransitiveBaseTraversalFunctionException, InterruptedException {
     Label label = (Label) key.argument();
     LoadTargetResults loadTargetResults;
     try {
@@ -157,9 +158,11 @@
    * <p>This method may return a precise set of aspect keys, but may need to request additional
    * dependencies from the env to do so.
    */
-  private Iterable<SkyKey> getStrictLabelAspectKeys(Target target,
-          Map<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>> depMap,
-          Environment env) {
+  private Iterable<SkyKey> getStrictLabelAspectKeys(
+      Target target,
+      Map<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>> depMap,
+      Environment env)
+      throws InterruptedException {
     List<SkyKey> depKeys = Lists.newArrayList();
     if (target instanceof Rule) {
       Map<Label, ValueOrException2<NoSuchPackageException, NoSuchTargetException>> labelDepMap =
@@ -189,9 +192,10 @@
       Attribute attr,
       Label toLabel,
       ValueOrException2<NoSuchPackageException, NoSuchTargetException> toVal,
-      Environment env);
+      Environment env)
+      throws InterruptedException;
 
-  private Iterable<SkyKey> getLabelDepKeys(Target target) {
+  private Iterable<SkyKey> getLabelDepKeys(Target target) throws InterruptedException {
     List<SkyKey> depKeys = Lists.newArrayList();
     for (Label depLabel : getLabelDeps(target)) {
       depKeys.add(getKey(depLabel));
@@ -200,7 +204,7 @@
   }
 
   // TODO(bazel-team): Unify this logic with that in LabelVisitor, and possibly DependencyResolver.
-  private static Iterable<Label> getLabelDeps(Target target) {
+  private static Iterable<Label> getLabelDeps(Target target) throws InterruptedException {
     final Set<Label> labels = new HashSet<>();
     if (target instanceof OutputFile) {
       Rule rule = ((OutputFile) target).getGeneratingRule();
@@ -217,7 +221,7 @@
     return labels;
   }
 
-  private static void visitRule(Target target, Set<Label> labels) {
+  private static void visitRule(Target target, Set<Label> labels) throws InterruptedException {
     labels.addAll(((Rule) target).getTransitions(DependencyFilter.NO_NODEP_ATTRIBUTES).values());
   }
 
@@ -295,7 +299,7 @@
   }
 
   private LoadTargetResults loadTarget(Environment env, Label label)
-      throws NoSuchTargetException, NoSuchPackageException {
+      throws NoSuchTargetException, NoSuchPackageException, InterruptedException {
     SkyKey packageKey = PackageValue.key(label.getPackageIdentifier());
     SkyKey targetKey = TargetMarkerValue.key(label);
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java
index 81e53e0..b620259 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java
@@ -118,10 +118,13 @@
   }
 
   @Override
-  void processDeps(TransitiveTargetValueBuilder builder, EventHandler eventHandler,
+  void processDeps(
+      TransitiveTargetValueBuilder builder,
+      EventHandler eventHandler,
       TargetAndErrorIfAny targetAndErrorIfAny,
       Iterable<Entry<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>>>
-          depEntries) {
+          depEntries)
+      throws InterruptedException {
     boolean successfulTransitiveLoading = builder.isSuccessfulTransitiveLoading();
     Target target = targetAndErrorIfAny.getTarget();
     NestedSetBuilder<Label> transitiveRootCauses = builder.getTransitiveRootCauses();
@@ -241,9 +244,13 @@
   }
 
   @Override
-  protected Collection<Label> getAspectLabels(Rule fromRule, Attribute attr, Label toLabel,
+  protected Collection<Label> getAspectLabels(
+      Rule fromRule,
+      Attribute attr,
+      Label toLabel,
       ValueOrException2<NoSuchPackageException, NoSuchTargetException> toVal,
-      final Environment env) {
+      final Environment env)
+      throws InterruptedException {
     SkyKey packageKey = PackageValue.key(toLabel.getPackageIdentifier());
     try {
       PackageValue pkgValue =
@@ -269,14 +276,15 @@
 
   @Override
   TargetMarkerValue getTargetMarkerValue(SkyKey targetMarkerKey, Environment env)
-      throws NoSuchTargetException, NoSuchPackageException {
+      throws NoSuchTargetException, NoSuchPackageException, InterruptedException {
     return (TargetMarkerValue)
         env.getValueOrThrow(
             targetMarkerKey, NoSuchTargetException.class, NoSuchPackageException.class);
   }
 
-  private void maybeReportErrorAboutMissingEdge(
-      Target target, Label depLabel, NoSuchThingException e, EventHandler eventHandler) {
+  private static void maybeReportErrorAboutMissingEdge(
+      Target target, Label depLabel, NoSuchThingException e, EventHandler eventHandler)
+      throws InterruptedException {
     if (e instanceof NoSuchTargetException) {
       NoSuchTargetException nste = (NoSuchTargetException) e;
       if (depLabel.equals(nste.getLabel())) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java
index 1852793..0a85af0 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java
@@ -29,10 +29,8 @@
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
 import com.google.devtools.build.skyframe.ValueOrException2;
-
 import java.util.Collection;
 import java.util.Map.Entry;
-
 import javax.annotation.Nullable;
 
 /**
@@ -117,7 +115,7 @@
 
   @Override
   TargetMarkerValue getTargetMarkerValue(SkyKey targetMarkerKey, Environment env)
-      throws NoSuchTargetException, NoSuchPackageException {
+      throws NoSuchTargetException, NoSuchPackageException, InterruptedException {
     return TargetMarkerFunction.computeTargetMarkerValue(targetMarkerKey, env);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceStatusFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceStatusFunction.java
index 4cd9099..12b36a4 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceStatusFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceStatusFunction.java
@@ -25,7 +25,7 @@
   }
 
   @Override
-  public SkyValue compute(SkyKey skyKey, Environment env) {
+  public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
     Preconditions.checkState(
         WorkspaceStatusValue.SKY_KEY.equals(skyKey), WorkspaceStatusValue.SKY_KEY);
 
diff --git a/src/main/java/com/google/devtools/build/skyframe/AbstractSkyFunctionEnvironment.java b/src/main/java/com/google/devtools/build/skyframe/AbstractSkyFunctionEnvironment.java
index a91fdbf..a4954e9 100644
--- a/src/main/java/com/google/devtools/build/skyframe/AbstractSkyFunctionEnvironment.java
+++ b/src/main/java/com/google/devtools/build/skyframe/AbstractSkyFunctionEnvironment.java
@@ -18,11 +18,9 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
 import com.google.devtools.build.skyframe.ValueOrExceptionUtils.BottomException;
-
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -32,14 +30,16 @@
 @VisibleForTesting
 public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Environment {
   protected boolean valuesMissing = false;
-  private <E extends Exception> ValueOrException<E> getValueOrException(SkyKey depKey,
-      Class<E> exceptionClass) {
+  private <E extends Exception> ValueOrException<E> getValueOrException(
+      SkyKey depKey, Class<E> exceptionClass) throws InterruptedException {
     return ValueOrExceptionUtils.downconvert(
         getValueOrException(depKey, exceptionClass, BottomException.class), exceptionClass);
   }
 
-  private <E1 extends Exception, E2 extends Exception> ValueOrException2<E1, E2>
-  getValueOrException(SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2) {
+  private <E1 extends Exception, E2 extends Exception>
+      ValueOrException2<E1, E2> getValueOrException(
+          SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2)
+          throws InterruptedException {
     return ValueOrExceptionUtils.downconvert(getValueOrException(depKey, exceptionClass1,
         exceptionClass2, BottomException.class), exceptionClass1, exceptionClass2);
   }
@@ -49,7 +49,8 @@
           SkyKey depKey,
           Class<E1> exceptionClass1,
           Class<E2> exceptionClass2,
-          Class<E3> exceptionClass3) {
+          Class<E3> exceptionClass3)
+          throws InterruptedException {
     return ValueOrExceptionUtils.downconvert(
         getValueOrException(depKey, exceptionClass1, exceptionClass2, exceptionClass3,
             BottomException.class),
@@ -64,7 +65,8 @@
           Class<E1> exceptionClass1,
           Class<E2> exceptionClass2,
           Class<E3> exceptionClass3,
-          Class<E4> exceptionClass4) {
+          Class<E4> exceptionClass4)
+          throws InterruptedException {
     return ValueOrExceptionUtils.downconvert(
         getValueOrException(depKey, exceptionClass1, exceptionClass2, exceptionClass3,
             exceptionClass4, BottomException.class),
@@ -74,15 +76,20 @@
         exceptionClass4);
   }
 
-  private <E1 extends Exception, E2 extends Exception, E3 extends Exception,
-           E4 extends Exception, E5 extends Exception>
+  private <
+          E1 extends Exception,
+          E2 extends Exception,
+          E3 extends Exception,
+          E4 extends Exception,
+          E5 extends Exception>
       ValueOrException5<E1, E2, E3, E4, E5> getValueOrException(
           SkyKey depKey,
           Class<E1> exceptionClass1,
           Class<E2> exceptionClass2,
           Class<E3> exceptionClass3,
           Class<E4> exceptionClass4,
-          Class<E5> exceptionClass5) {
+          Class<E5> exceptionClass5)
+          throws InterruptedException {
     return getValueOrExceptions(
         ImmutableSet.of(depKey),
         exceptionClass1,
@@ -92,7 +99,11 @@
         exceptionClass5).get(depKey);
   }
 
-  private <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception,
+  private <
+          E1 extends Exception,
+          E2 extends Exception,
+          E3 extends Exception,
+          E4 extends Exception,
           E5 extends Exception>
       Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValueOrExceptions(
           Set<SkyKey> depKeys,
@@ -100,7 +111,8 @@
           final Class<E2> exceptionClass2,
           final Class<E3> exceptionClass3,
           final Class<E4> exceptionClass4,
-          final Class<E5> exceptionClass5) {
+          final Class<E5> exceptionClass5)
+          throws InterruptedException {
     SkyFunctionException.validateExceptionType(exceptionClass1);
     SkyFunctionException.validateExceptionType(exceptionClass2);
     SkyFunctionException.validateExceptionType(exceptionClass3);
@@ -158,11 +170,11 @@
 
   /** Implementations should set {@link #valuesMissing} as necessary. */
   protected abstract Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(
-      Set<SkyKey> depKeys);
+      Set<SkyKey> depKeys) throws InterruptedException;
 
   @Override
   @Nullable
-  public SkyValue getValue(SkyKey depKey) {
+  public SkyValue getValue(SkyKey depKey) throws InterruptedException {
     try {
       return getValueOrThrow(depKey, BottomException.class);
     } catch (BottomException e) {
@@ -173,16 +185,15 @@
   @Override
   @Nullable
   public <E extends Exception> SkyValue getValueOrThrow(SkyKey depKey, Class<E> exceptionClass)
-      throws E {
+      throws E, InterruptedException {
     return getValueOrException(depKey, exceptionClass).get();
   }
 
   @Override
   @Nullable
   public <E1 extends Exception, E2 extends Exception> SkyValue getValueOrThrow(
-      SkyKey depKey,
-      Class<E1> exceptionClass1,
-      Class<E2> exceptionClass2) throws E1, E2 {
+      SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2)
+      throws E1, E2, InterruptedException {
     return getValueOrException(depKey, exceptionClass1, exceptionClass2).get();
   }
 
@@ -193,7 +204,8 @@
           SkyKey depKey,
           Class<E1> exceptionClass1,
           Class<E2> exceptionClass2,
-          Class<E3> exceptionClass3) throws E1, E2, E3 {
+          Class<E3> exceptionClass3)
+          throws E1, E2, E3, InterruptedException {
     return getValueOrException(depKey, exceptionClass1, exceptionClass2, exceptionClass3).get();
   }
 
@@ -204,7 +216,8 @@
           Class<E1> exceptionClass1,
           Class<E2> exceptionClass2,
           Class<E3> exceptionClass3,
-          Class<E4> exceptionClass4) throws E1, E2, E3, E4 {
+          Class<E4> exceptionClass4)
+          throws E1, E2, E3, E4, InterruptedException {
     return getValueOrException(
         depKey,
         exceptionClass1,
@@ -214,7 +227,11 @@
   }
 
   @Override
-  public <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception,
+  public <
+          E1 extends Exception,
+          E2 extends Exception,
+          E3 extends Exception,
+          E4 extends Exception,
           E5 extends Exception>
       SkyValue getValueOrThrow(
           SkyKey depKey,
@@ -222,8 +239,8 @@
           Class<E2> exceptionClass2,
           Class<E3> exceptionClass3,
           Class<E4> exceptionClass4,
-          Class<E5> exceptionClass5
-  ) throws E1, E2, E3, E4, E5 {
+          Class<E5> exceptionClass5)
+          throws E1, E2, E3, E4, E5, InterruptedException {
     return getValueOrException(
         depKey,
         exceptionClass1,
@@ -234,14 +251,14 @@
   }
 
   @Override
-  public Map<SkyKey, SkyValue> getValues(Iterable<SkyKey> depKeys) {
+  public Map<SkyKey, SkyValue> getValues(Iterable<SkyKey> depKeys) throws InterruptedException {
     return Maps.transformValues(getValuesOrThrow(depKeys, BottomException.class),
         GET_VALUE_FROM_VOE);
   }
 
   @Override
   public <E extends Exception> Map<SkyKey, ValueOrException<E>> getValuesOrThrow(
-      Iterable<SkyKey> depKeys, Class<E> exceptionClass) {
+      Iterable<SkyKey> depKeys, Class<E> exceptionClass) throws InterruptedException {
     return Maps.transformValues(
         getValuesOrThrow(depKeys, exceptionClass, BottomException.class),
         makeSafeDowncastToVOEFunction(exceptionClass));
@@ -250,9 +267,8 @@
   @Override
   public <E1 extends Exception, E2 extends Exception>
       Map<SkyKey, ValueOrException2<E1, E2>> getValuesOrThrow(
-          Iterable<SkyKey> depKeys,
-          Class<E1> exceptionClass1,
-          Class<E2> exceptionClass2) {
+          Iterable<SkyKey> depKeys, Class<E1> exceptionClass1, Class<E2> exceptionClass2)
+          throws InterruptedException {
     return Maps.transformValues(
         getValuesOrThrow(depKeys, exceptionClass1, exceptionClass2, BottomException.class),
         makeSafeDowncastToVOE2Function(exceptionClass1, exceptionClass2));
@@ -264,7 +280,8 @@
           Iterable<SkyKey> depKeys,
           Class<E1> exceptionClass1,
           Class<E2> exceptionClass2,
-          Class<E3> exceptionClass3) {
+          Class<E3> exceptionClass3)
+          throws InterruptedException {
     return Maps.transformValues(
         getValuesOrThrow(depKeys, exceptionClass1, exceptionClass2, exceptionClass3,
             BottomException.class),
@@ -278,7 +295,8 @@
           Class<E1> exceptionClass1,
           Class<E2> exceptionClass2,
           Class<E3> exceptionClass3,
-          Class<E4> exceptionClass4) {
+          Class<E4> exceptionClass4)
+          throws InterruptedException {
     return Maps.transformValues(
         getValuesOrThrow(depKeys, exceptionClass1, exceptionClass2, exceptionClass3,
             exceptionClass4, BottomException.class),
@@ -287,15 +305,20 @@
   }
 
   @Override
-  public <E1 extends Exception, E2 extends Exception, E3 extends Exception,
-          E4 extends Exception, E5 extends Exception>
+  public <
+          E1 extends Exception,
+          E2 extends Exception,
+          E3 extends Exception,
+          E4 extends Exception,
+          E5 extends Exception>
       Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValuesOrThrow(
           Iterable<SkyKey> depKeys,
           Class<E1> exceptionClass1,
           Class<E2> exceptionClass2,
           Class<E3> exceptionClass3,
           Class<E4> exceptionClass4,
-          Class<E5> exceptionClass5) {
+          Class<E5> exceptionClass5)
+          throws InterruptedException {
     Set<SkyKey> keys = ImmutableSet.copyOf(depKeys);
     Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> result = getValueOrExceptions(keys,
         exceptionClass1, exceptionClass2, exceptionClass3, exceptionClass4, exceptionClass5);
diff --git a/src/main/java/com/google/devtools/build/skyframe/BuildDriver.java b/src/main/java/com/google/devtools/build/skyframe/BuildDriver.java
index 3172b4a..4ebe244 100644
--- a/src/main/java/com/google/devtools/build/skyframe/BuildDriver.java
+++ b/src/main/java/com/google/devtools/build/skyframe/BuildDriver.java
@@ -17,7 +17,6 @@
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.util.AbruptExitException;
 import com.google.devtools.common.options.OptionsClassProvider;
-
 import javax.annotation.Nullable;
 
 /** A BuildDriver wraps a MemoizingEvaluator, passing along the proper Version. */
@@ -41,11 +40,11 @@
   MemoizingEvaluator getGraphForTesting();
 
   @Nullable
-  SkyValue getExistingValueForTesting(SkyKey key);
+  SkyValue getExistingValueForTesting(SkyKey key) throws InterruptedException;
 
   @Nullable
-  ErrorInfo getExistingErrorForTesting(SkyKey key);
+  ErrorInfo getExistingErrorForTesting(SkyKey key) throws InterruptedException;
 
   @Nullable
-  NodeEntry getEntryForTesting(SkyKey key);
+  NodeEntry getEntryForTesting(SkyKey key) throws InterruptedException;
 }
diff --git a/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java
index d714924..6bf77ec4 100644
--- a/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java
+++ b/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java
@@ -15,10 +15,8 @@
 
 import com.google.devtools.build.lib.util.GroupedList;
 import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper;
-
 import java.util.Collection;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /** Convenience class for {@link NodeEntry} implementations that delegate many operations. */
@@ -35,23 +33,23 @@
   }
 
   @Override
-  public SkyValue getValue() {
+  public SkyValue getValue() throws InterruptedException {
     return getDelegate().getValue();
   }
 
   @Override
-  public SkyValue getValueMaybeWithMetadata() {
+  public SkyValue getValueMaybeWithMetadata() throws InterruptedException {
     return getDelegate().getValueMaybeWithMetadata();
   }
 
   @Override
-  public SkyValue toValue() {
+  public SkyValue toValue() throws InterruptedException {
     return getDelegate().toValue();
   }
 
   @Nullable
   @Override
-  public ErrorInfo getErrorInfo() {
+  public ErrorInfo getErrorInfo() throws InterruptedException {
     return getDelegate().getErrorInfo();
   }
 
@@ -61,7 +59,7 @@
   }
 
   @Override
-  public Set<SkyKey> setValue(SkyValue value, Version version) {
+  public Set<SkyKey> setValue(SkyValue value, Version version) throws InterruptedException {
     return getDelegate().setValue(value, version);
   }
 
@@ -86,7 +84,7 @@
   }
 
   @Override
-  public Set<SkyKey> markClean() {
+  public Set<SkyKey> markClean() throws InterruptedException {
     return getDelegate().markClean();
   }
 
@@ -156,7 +154,7 @@
   }
 
   @Override
-  public Iterable<SkyKey> getDirectDeps() {
+  public Iterable<SkyKey> getDirectDeps() throws InterruptedException {
     return getDelegate().getDirectDeps();
   }
 
@@ -187,7 +185,7 @@
 
   @Override
   @Nullable
-  public MarkedDirtyResult markDirty(boolean isChanged) {
+  public MarkedDirtyResult markDirty(boolean isChanged) throws InterruptedException {
     return getThinDelegate().markDirty(isChanged);
   }
 
diff --git a/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java b/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java
index c56bf55..5c22a05 100644
--- a/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java
+++ b/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java
@@ -13,8 +13,6 @@
 // limitations under the License.
 package com.google.devtools.build.skyframe;
 
-import com.google.common.base.Function;
-import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
 import com.google.devtools.build.lib.util.Preconditions;
@@ -22,7 +20,6 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
-
 import javax.annotation.Nullable;
 
 /**
@@ -35,7 +32,7 @@
     this.graph = graph;
   }
 
-  private NodeEntry getEntryForValue(SkyKey key) {
+  private NodeEntry getEntryForValue(SkyKey key) throws InterruptedException {
     NodeEntry entry =
         Preconditions.checkNotNull(
             graph.getBatch(null, Reason.WALKABLE_GRAPH_VALUE, ImmutableList.of(key)).get(key),
@@ -45,7 +42,7 @@
   }
 
   @Override
-  public boolean exists(SkyKey key) {
+  public boolean exists(SkyKey key) throws InterruptedException {
     NodeEntry entry =
         graph.getBatch(null, Reason.EXISTENCE_CHECKING, ImmutableList.of(key)).get(key);
     return entry != null && entry.isDone();
@@ -53,32 +50,35 @@
 
   @Nullable
   @Override
-  public SkyValue getValue(SkyKey key) {
+  public SkyValue getValue(SkyKey key) throws InterruptedException {
     return getEntryForValue(key).getValue();
   }
 
-  private static final Function<NodeEntry, SkyValue> GET_SKY_VALUE_FUNCTION =
-      new Function<NodeEntry, SkyValue>() {
-        @Nullable
-        @Override
-        public SkyValue apply(NodeEntry entry) {
-          return entry.isDone() ? entry.getValue() : null;
-        }
-      };
-
-  @Override
-  public Map<SkyKey, SkyValue> getSuccessfulValues(Iterable<SkyKey> keys) {
-    return Maps.filterValues(
-        Maps.transformValues(
-            graph.getBatch(null, Reason.WALKABLE_GRAPH_VALUE, keys),
-            GET_SKY_VALUE_FUNCTION),
-        Predicates.notNull());
+  private static SkyValue getValue(NodeEntry entry) throws InterruptedException {
+    return entry.isDone() ? entry.getValue() : null;
   }
 
   @Override
-  public Map<SkyKey, Exception> getMissingAndExceptions(Iterable<SkyKey> keys) {
+  public Map<SkyKey, SkyValue> getSuccessfulValues(Iterable<SkyKey> keys)
+      throws InterruptedException {
+    Map<SkyKey, ? extends NodeEntry> batchGet =
+        graph.getBatch(null, Reason.WALKABLE_GRAPH_VALUE, keys);
+    Map<SkyKey, SkyValue> result = Maps.newHashMapWithExpectedSize(batchGet.size());
+    for (Entry<SkyKey, ? extends NodeEntry> entryPair : batchGet.entrySet()) {
+      SkyValue value = getValue(entryPair.getValue());
+      if (value != null) {
+        result.put(entryPair.getKey(), value);
+      }
+    }
+    return result;
+  }
+
+  @Override
+  public Map<SkyKey, Exception> getMissingAndExceptions(Iterable<SkyKey> keys)
+      throws InterruptedException {
     Map<SkyKey, Exception> result = new HashMap<>();
-    Map<SkyKey, NodeEntry> graphResult = graph.getBatch(null, Reason.WALKABLE_GRAPH_VALUE, keys);
+    Map<SkyKey, ? extends NodeEntry> graphResult =
+        graph.getBatch(null, Reason.WALKABLE_GRAPH_VALUE, keys);
     for (SkyKey key : keys) {
       NodeEntry nodeEntry = graphResult.get(key);
       if (nodeEntry == null || !nodeEntry.isDone()) {
@@ -95,16 +95,18 @@
 
   @Nullable
   @Override
-  public Exception getException(SkyKey key) {
+  public Exception getException(SkyKey key) throws InterruptedException {
     ErrorInfo errorInfo = getEntryForValue(key).getErrorInfo();
     return errorInfo == null ? null : errorInfo.getException();
   }
 
   @Override
-  public Map<SkyKey, Iterable<SkyKey>> getDirectDeps(Iterable<SkyKey> keys) {
-    Map<SkyKey, NodeEntry> entries = graph.getBatch(null, Reason.WALKABLE_GRAPH_DEPS, keys);
+  public Map<SkyKey, Iterable<SkyKey>> getDirectDeps(Iterable<SkyKey> keys)
+      throws InterruptedException {
+    Map<SkyKey, ? extends NodeEntry> entries =
+        graph.getBatch(null, Reason.WALKABLE_GRAPH_DEPS, keys);
     Map<SkyKey, Iterable<SkyKey>> result = new HashMap<>(entries.size());
-    for (Entry<SkyKey, NodeEntry> entry : entries.entrySet()) {
+    for (Entry<SkyKey, ? extends NodeEntry> entry : entries.entrySet()) {
       Preconditions.checkState(entry.getValue().isDone(), entry);
       result.put(entry.getKey(), entry.getValue().getDirectDeps());
     }
@@ -112,10 +114,12 @@
   }
 
   @Override
-  public Map<SkyKey, Iterable<SkyKey>> getReverseDeps(Iterable<SkyKey> keys) {
-    Map<SkyKey, NodeEntry> entries = graph.getBatch(null, Reason.WALKABLE_GRAPH_RDEPS, keys);
+  public Map<SkyKey, Iterable<SkyKey>> getReverseDeps(Iterable<SkyKey> keys)
+      throws InterruptedException {
+    Map<SkyKey, ? extends NodeEntry> entries =
+        graph.getBatch(null, Reason.WALKABLE_GRAPH_RDEPS, keys);
     Map<SkyKey, Iterable<SkyKey>> result = new HashMap<>(entries.size());
-    for (Entry<SkyKey, NodeEntry> entry : entries.entrySet()) {
+    for (Entry<SkyKey, ? extends NodeEntry> entry : entries.entrySet()) {
       Preconditions.checkState(entry.getValue().isDone(), entry);
       result.put(entry.getKey(), entry.getValue().getReverseDeps());
     }
diff --git a/src/main/java/com/google/devtools/build/skyframe/DirtyBuildingState.java b/src/main/java/com/google/devtools/build/skyframe/DirtyBuildingState.java
index e8c5a46..a476275 100644
--- a/src/main/java/com/google/devtools/build/skyframe/DirtyBuildingState.java
+++ b/src/main/java/com/google/devtools/build/skyframe/DirtyBuildingState.java
@@ -18,7 +18,6 @@
 import com.google.devtools.build.lib.util.GroupedList;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.skyframe.NodeEntry.DirtyState;
-
 import java.util.Collection;
 import java.util.Set;
 
@@ -48,7 +47,7 @@
   protected final GroupedList<SkyKey> lastBuildDirectDeps;
 
   /** The value of the node the last time it was built. */
-  protected abstract SkyValue getLastBuildValue();
+  protected abstract SkyValue getLastBuildValue() throws InterruptedException;
 
   /**
    * Group of children to be checked next in the process of determining if this entry needs to be
@@ -144,7 +143,7 @@
    * <p>Changes in direct deps do <i>not</i> force this to return false. Only the value is
    * considered.
    */
-  final boolean unchangedFromLastBuild(SkyValue newValue) {
+  final boolean unchangedFromLastBuild(SkyValue newValue) throws InterruptedException {
     checkFinishedBuildingWhenAboutToSetValue();
     return !(newValue instanceof NotComparableSkyValue) && getLastBuildValue().equals(newValue);
   }
diff --git a/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java b/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java
index 5dba03d..71537e8 100644
--- a/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java
@@ -20,10 +20,8 @@
 import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DeletingNodeVisitor;
 import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DirtyingNodeVisitor;
 import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationState;
-
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ForkJoinPool;
-
 import javax.annotation.Nullable;
 
 /**
@@ -106,8 +104,7 @@
             state,
             dirtyKeyTracker,
             forkJoinPool,
-            supportInterruptions,
-            errorHandler);
+            supportInterruptions);
   }
 
   /**
@@ -141,8 +138,7 @@
       InvalidationState state,
       DirtyKeyTracker dirtyKeyTracker,
       ForkJoinPool forkJoinPool,
-      boolean supportInterruptions,
-      ErrorHandler errorHandler)
+      boolean supportInterruptions)
       throws InterruptedException {
     DirtyingNodeVisitor visitor =
         createInvalidatingVisitorIfNeeded(
@@ -153,7 +149,7 @@
             dirtyKeyTracker,
             forkJoinPool,
             supportInterruptions,
-            errorHandler);
+            ErrorHandler.NullHandler.INSTANCE);
     if (visitor != null) {
       visitor.run();
     }
diff --git a/src/main/java/com/google/devtools/build/skyframe/EvaluableGraph.java b/src/main/java/com/google/devtools/build/skyframe/EvaluableGraph.java
index 6e93ce4..51ba403 100644
--- a/src/main/java/com/google/devtools/build/skyframe/EvaluableGraph.java
+++ b/src/main/java/com/google/devtools/build/skyframe/EvaluableGraph.java
@@ -20,18 +20,21 @@
 /**
  * Interface between a single version of the graph and the evaluator. Supports mutation of that
  * single version of the graph.
+ *
+ * <p>Certain graph implementations can throw {@link InterruptedException} when trying to retrieve
+ * node entries. Such exceptions should not be caught locally -- they should be allowed to propagate
+ * up.
  */
 @ThreadSafe
 interface EvaluableGraph extends QueryableGraph, DeletableGraph {
   /**
-   * Like {@link QueryableGraph#getBatch}, except it creates a new node for each key
-   * not already present in the graph. Thus, the returned map will have an entry for each key in
-   * {@code keys}.
+   * Like {@link QueryableGraph#getBatch}, except it creates a new node for each key not already
+   * present in the graph. Thus, the returned map will have an entry for each key in {@code keys}.
    *
    * @param requestor if non-{@code null}, the node on behalf of which the given {@code keys} are
    *     being requested.
    * @param reason the reason the nodes are being requested.
    */
-  Map<SkyKey, NodeEntry> createIfAbsentBatch(
-      @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys);
+  Map<SkyKey, ? extends NodeEntry> createIfAbsentBatch(
+      @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) throws InterruptedException;
 }
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java
index 02735c0..edb80f0 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java
@@ -14,9 +14,22 @@
 package com.google.devtools.build.skyframe;
 
 import java.util.Map;
+import javax.annotation.Nullable;
 
 /** {@link ProcessableGraph} that exposes the contents of the entire graph. */
 interface InMemoryGraph extends ProcessableGraph {
+  @Override
+  Map<SkyKey, ? extends NodeEntry> createIfAbsentBatch(
+      @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys);
+
+  @Nullable
+  @Override
+  NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key);
+
+  @Override
+  Map<SkyKey, ? extends NodeEntry> getBatch(
+      @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys);
+
   /**
    * Returns a read-only live view of the nodes in the graph. All node are included. Dirty values
    * include their Node value. Values in error have a null value.
@@ -30,5 +43,5 @@
   Map<SkyKey, SkyValue> getDoneValues();
 
   // Only for use by MemoizingEvaluator#delete
-  Map<SkyKey, NodeEntry> getAllValues();
+  Map<SkyKey, ? extends NodeEntry> getAllValues();
 }
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java
index eca58b3..b5d2472 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java
@@ -32,7 +32,7 @@
  */
 public class InMemoryGraphImpl implements InMemoryGraph {
 
-  protected final ConcurrentMap<SkyKey, NodeEntry> nodeMap =
+  protected final ConcurrentMap<SkyKey, InMemoryNodeEntry> nodeMap =
       new MapMaker().initialCapacity(1024).concurrencyLevel(200).makeMap();
   private final boolean keepEdges;
 
@@ -50,7 +50,7 @@
   }
 
   @Override
-  public NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey skyKey) {
+  public InMemoryNodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey skyKey) {
     return nodeMap.get(skyKey);
   }
 
@@ -58,7 +58,7 @@
   public Map<SkyKey, NodeEntry> getBatch(SkyKey requestor, Reason reason, Iterable<SkyKey> keys) {
     ImmutableMap.Builder<SkyKey, NodeEntry> builder = ImmutableMap.builder();
     for (SkyKey key : keys) {
-      NodeEntry entry = get(null, reason, key);
+      InMemoryNodeEntry entry = get(null, Reason.OTHER, key);
       if (entry != null) {
         builder.put(key, entry);
       }
@@ -66,16 +66,17 @@
     return builder.build();
   }
 
-  protected NodeEntry createIfAbsent(SkyKey key) {
-    NodeEntry newval = keepEdges ? new InMemoryNodeEntry() : new EdgelessInMemoryNodeEntry();
-    NodeEntry oldval = nodeMap.putIfAbsent(key, newval);
+  protected InMemoryNodeEntry createIfAbsent(SkyKey key) {
+    InMemoryNodeEntry newval =
+        keepEdges ? new InMemoryNodeEntry() : new EdgelessInMemoryNodeEntry();
+    InMemoryNodeEntry oldval = nodeMap.putIfAbsent(key, newval);
     return oldval == null ? newval : oldval;
   }
 
   @Override
-  public Map<SkyKey, NodeEntry> createIfAbsentBatch(
+  public Map<SkyKey, InMemoryNodeEntry> createIfAbsentBatch(
       @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) {
-    ImmutableMap.Builder<SkyKey, NodeEntry> builder = ImmutableMap.builder();
+    ImmutableMap.Builder<SkyKey, InMemoryNodeEntry> builder = ImmutableMap.builder();
     for (SkyKey key : keys) {
       builder.put(key, createIfAbsent(key));
     }
@@ -87,9 +88,9 @@
     return Collections.unmodifiableMap(
         Maps.transformValues(
             nodeMap,
-            new Function<NodeEntry, SkyValue>() {
+            new Function<InMemoryNodeEntry, SkyValue>() {
               @Override
-              public SkyValue apply(NodeEntry entry) {
+              public SkyValue apply(InMemoryNodeEntry entry) {
                 return entry.toValue();
               }
             }));
@@ -101,9 +102,9 @@
         Maps.filterValues(
             Maps.transformValues(
                 nodeMap,
-                new Function<NodeEntry, SkyValue>() {
+                new Function<InMemoryNodeEntry, SkyValue>() {
                   @Override
-                  public SkyValue apply(NodeEntry entry) {
+                  public SkyValue apply(InMemoryNodeEntry entry) {
                     return entry.isDone() ? entry.getValue() : null;
                   }
                 }),
@@ -111,12 +112,12 @@
   }
 
   @Override
-  public Map<SkyKey, NodeEntry> getAllValues() {
+  public Map<SkyKey, InMemoryNodeEntry> getAllValues() {
     return Collections.unmodifiableMap(nodeMap);
   }
 
   @VisibleForTesting
-  protected ConcurrentMap<SkyKey, NodeEntry> getNodeMap() {
+  protected ConcurrentMap<SkyKey, ? extends NodeEntry> getNodeMap() {
     return nodeMap;
   }
 
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
index 38604ed..972d020 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
@@ -39,7 +39,6 @@
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
-
 import javax.annotation.Nullable;
 
 /**
@@ -112,13 +111,16 @@
   @Override
   public void delete(final Predicate<SkyKey> deletePredicate) {
     valuesToDelete.addAll(
-        Maps.filterEntries(graph.getAllValues(), new Predicate<Entry<SkyKey, NodeEntry>>() {
-          @Override
-          public boolean apply(Entry<SkyKey, NodeEntry> input) {
-            Preconditions.checkNotNull(input.getKey(), "Null SkyKey in entry: %s", input);
-            return input.getValue().isDirty() || deletePredicate.apply(input.getKey());
-          }
-        }).keySet());
+        Maps.filterEntries(
+                graph.getAllValues(),
+                new Predicate<Entry<SkyKey, ? extends NodeEntry>>() {
+                  @Override
+                  public boolean apply(Entry<SkyKey, ? extends NodeEntry> input) {
+                    Preconditions.checkNotNull(input.getKey(), "Null SkyKey in entry: %s", input);
+                    return input.getValue().isDirty() || deletePredicate.apply(input.getKey());
+                  }
+                })
+            .keySet());
   }
 
   @Override
@@ -209,12 +211,18 @@
       SkyValue newValue = entry.getValue();
       NodeEntry prevEntry = graph.get(null, Reason.OTHER, key);
       if (prevEntry != null && prevEntry.isDone()) {
-        Iterable<SkyKey> directDeps = prevEntry.getDirectDeps();
-        Preconditions.checkState(Iterables.isEmpty(directDeps),
-            "existing entry for %s has deps: %s", key, directDeps);
-        if (newValue.equals(prevEntry.getValue())
-            && !valuesToDirty.contains(key) && !valuesToDelete.contains(key)) {
-          it.remove();
+        try {
+          Iterable<SkyKey> directDeps = prevEntry.getDirectDeps();
+          Preconditions.checkState(
+              Iterables.isEmpty(directDeps), "existing entry for %s has deps: %s", key, directDeps);
+          if (newValue.equals(prevEntry.getValue())
+              && !valuesToDirty.contains(key)
+              && !valuesToDelete.contains(key)) {
+            it.remove();
+          }
+        } catch (InterruptedException e) {
+          throw new IllegalStateException(
+              "InMemoryGraph does not throw: " + entry + ", " + prevEntry, e);
         }
       }
     }
@@ -227,7 +235,11 @@
     if (valuesToInject.isEmpty()) {
       return;
     }
-    ParallelEvaluator.injectValues(valuesToInject, version, graph, dirtyKeyTracker);
+    try {
+      ParallelEvaluator.injectValues(valuesToInject, version, graph, dirtyKeyTracker);
+    } catch (InterruptedException e) {
+      throw new IllegalStateException("InMemoryGraph doesn't throw interrupts", e);
+    }
     // Start with a new map to avoid bloat since clear() does not downsize the map.
     valuesToInject = new HashMap<>();
   }
@@ -268,13 +280,21 @@
   @Override
   @Nullable public SkyValue getExistingValueForTesting(SkyKey key) {
     NodeEntry entry = getExistingEntryForTesting(key);
-    return isDone(entry) ? entry.getValue() : null;
+    try {
+      return isDone(entry) ? entry.getValue() : null;
+    } catch (InterruptedException e) {
+      throw new IllegalStateException("InMemoryGraph does not throw" + key + ", " + entry, e);
+    }
   }
 
   @Override
   @Nullable public ErrorInfo getExistingErrorForTesting(SkyKey key) {
     NodeEntry entry = getExistingEntryForTesting(key);
-    return isDone(entry) ? entry.getErrorInfo() : null;
+    try {
+      return isDone(entry) ? entry.getErrorInfo() : null;
+    } catch (InterruptedException e) {
+      throw new IllegalStateException("InMemoryGraph does not throw" + key + ", " + entry, e);
+    }
   }
 
   @Nullable
@@ -300,7 +320,11 @@
       for (NodeEntry entry : graph.getAllValues().values()) {
         nodes++;
         if (entry.isDone()) {
-          edges += Iterables.size(entry.getDirectDeps());
+          try {
+            edges += Iterables.size(entry.getDirectDeps());
+          } catch (InterruptedException e) {
+            throw new IllegalStateException("InMemoryGraph doesn't throw: " + entry, e);
+          }
         }
       }
       out.println("Node count: " + nodes);
@@ -315,14 +339,18 @@
             }
           };
 
-      for (Entry<SkyKey, NodeEntry> mapPair : graph.getAllValues().entrySet()) {
+      for (Entry<SkyKey, ? extends NodeEntry> mapPair : graph.getAllValues().entrySet()) {
         SkyKey key = mapPair.getKey();
         NodeEntry entry = mapPair.getValue();
         if (entry.isDone()) {
           out.print(keyFormatter.apply(key));
           out.print("|");
-          out.println(Joiner.on('|').join(
-              Iterables.transform(entry.getDirectDeps(), keyFormatter)));
+          try {
+            out.println(
+                Joiner.on('|').join(Iterables.transform(entry.getDirectDeps(), keyFormatter)));
+          } catch (InterruptedException e) {
+            throw new IllegalStateException("InMemoryGraph doesn't throw: " + entry, e);
+          }
         }
       }
     }
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
index 9ba0dbe..82d6922 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
@@ -21,11 +21,9 @@
 import com.google.devtools.build.lib.util.GroupedList;
 import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -163,9 +161,13 @@
     if (isDone()) {
       return getErrorInfo() == null ? getValue() : null;
     } else if (isChanged() || isDirty()) {
-      return (getDirtyBuildingState().getLastBuildValue() == null)
-          ? null
-          : ValueWithMetadata.justValue(getDirtyBuildingState().getLastBuildValue());
+      SkyValue lastBuildValue = null;
+      try {
+        lastBuildValue = getDirtyBuildingState().getLastBuildValue();
+      } catch (InterruptedException e) {
+        throw new IllegalStateException("Interruption unexpected: " + this, e);
+      }
+      return (lastBuildValue == null) ? null : ValueWithMetadata.justValue(lastBuildValue);
     } else {
       // Value has not finished evaluating. It's probably about to be cleaned from the graph.
       return null;
@@ -230,7 +232,8 @@
   }
 
   @Override
-  public synchronized Set<SkyKey> setValue(SkyValue value, Version version) {
+  public synchronized Set<SkyKey> setValue(SkyValue value, Version version)
+      throws InterruptedException {
     Preconditions.checkState(isReady(), "%s %s", this, value);
     // This check may need to be removed when we move to a non-linear versioning sequence.
     Preconditions.checkState(
@@ -370,7 +373,7 @@
   }
 
   @Override
-  public synchronized Set<SkyKey> markClean() {
+  public synchronized Set<SkyKey> markClean() throws InterruptedException {
     this.value = getDirtyBuildingState().getLastBuildValue();
     Preconditions.checkState(isReady(), "Should be ready when clean: %s", this);
     Preconditions.checkState(
diff --git a/src/main/java/com/google/devtools/build/skyframe/InterruptibleSupplier.java b/src/main/java/com/google/devtools/build/skyframe/InterruptibleSupplier.java
new file mode 100644
index 0000000..5f4ab55
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skyframe/InterruptibleSupplier.java
@@ -0,0 +1,63 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.skyframe;
+
+import javax.annotation.Nullable;
+
+/** Supplier that may throw {@link InterruptedException} when value is retrieved. */
+public interface InterruptibleSupplier<T> {
+  T get() throws InterruptedException;
+
+  class Instance<T> implements InterruptibleSupplier<T> {
+    private final T instance;
+
+    public Instance(T instance) {
+      this.instance = instance;
+    }
+
+    @Override
+    public T get() {
+      return instance;
+    }
+  }
+
+  class Memoize<T> implements InterruptibleSupplier<T> {
+    private final InterruptibleSupplier<T> delegate;
+    private @Nullable T value = null;
+
+    private Memoize(InterruptibleSupplier<T> delegate) {
+      this.delegate = delegate;
+    }
+
+    public static <S> InterruptibleSupplier<S> of(InterruptibleSupplier<S> delegate) {
+      if (delegate instanceof Memoize) {
+        return delegate;
+      }
+      return new Memoize<>(delegate);
+    }
+
+    @Override
+    public T get() throws InterruptedException {
+      if (value != null) {
+        return value;
+      }
+      synchronized (this) {
+        if (value == null) {
+          value = delegate.get();
+        }
+      }
+      return value;
+    }
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/skyframe/InvalidatingNodeVisitor.java b/src/main/java/com/google/devtools/build/skyframe/InvalidatingNodeVisitor.java
index 543ccf4..096fc2d 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InvalidatingNodeVisitor.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InvalidatingNodeVisitor.java
@@ -22,7 +22,6 @@
 import com.google.common.collect.Sets;
 import com.google.devtools.build.lib.concurrent.AbstractQueueVisitor;
 import com.google.devtools.build.lib.concurrent.ErrorClassifier;
-import com.google.devtools.build.lib.concurrent.ErrorHandler;
 import com.google.devtools.build.lib.concurrent.ExecutorParams;
 import com.google.devtools.build.lib.concurrent.ForkJoinQuiescingExecutor;
 import com.google.devtools.build.lib.concurrent.QuiescingExecutor;
@@ -31,7 +30,6 @@
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.skyframe.QueryableGraph.Reason;
 import com.google.devtools.build.skyframe.ThinNodeEntry.MarkedDirtyResult;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Map;
@@ -41,7 +39,6 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.TimeUnit;
-
 import javax.annotation.Nullable;
 
 /**
@@ -113,8 +110,7 @@
             /*failFastOnException=*/ true,
             "skyframe-invalidator",
             executorFactory,
-            errorClassifier,
-            ErrorHandler.NullHandler.INSTANCE);
+            errorClassifier);
     this.graph = Preconditions.checkNotNull(graph);
     this.invalidationReceiver = invalidationReceiver;
     this.dirtyKeyTracker = Preconditions.checkNotNull(dirtyKeyTracker);
@@ -126,9 +122,8 @@
       @Nullable EvaluationProgressReceiver invalidationReceiver,
       InvalidationState state,
       DirtyKeyTracker dirtyKeyTracker,
-      ForkJoinPool forkJoinPool,
-      ErrorHandler errorHandler) {
-    this.executor = new ForkJoinQuiescingExecutor(forkJoinPool, errorClassifier, errorHandler);
+      ForkJoinPool forkJoinPool) {
+    this.executor = new ForkJoinQuiescingExecutor(forkJoinPool, errorClassifier);
     this.graph = Preconditions.checkNotNull(graph);
     this.invalidationReceiver = invalidationReceiver;
     this.dirtyKeyTracker = Preconditions.checkNotNull(dirtyKeyTracker);
@@ -270,7 +265,7 @@
       for (SkyKey key : unvisitedKeys) {
         pendingVisitations.add(Pair.of(key, InvalidationType.DELETED));
       }
-      final Map<SkyKey, NodeEntry> entries =
+      final Map<SkyKey, ? extends NodeEntry> entries =
           graph.getBatch(null, Reason.INVALIDATION, unvisitedKeys);
       for (final SkyKey key : unvisitedKeys) {
         executor.execute(
@@ -303,13 +298,23 @@
                       entry.isDone()
                           ? ImmutableSet.<SkyKey>of()
                           : entry.getTemporaryDirectDeps().toSet();
-                  Iterable<SkyKey> directDeps =
-                      entry.isDone()
-                          ? entry.getDirectDeps()
-                          : entry.getAllDirectDepsForIncompleteNode();
-                  Map<SkyKey, NodeEntry> depMap =
+                  Iterable<SkyKey> directDeps;
+                  try {
+                    directDeps =
+                        entry.isDone()
+                            ? entry.getDirectDeps()
+                            : entry.getAllDirectDepsForIncompleteNode();
+                  } catch (InterruptedException e) {
+                    throw new IllegalStateException(
+                        "Deletion cannot happen on a graph that may have blocking operations: "
+                            + key
+                            + ", "
+                            + entry,
+                        e);
+                  }
+                  Map<SkyKey, ? extends NodeEntry> depMap =
                       graph.getBatch(key, Reason.INVALIDATION, directDeps);
-                  for (Map.Entry<SkyKey, NodeEntry> directDepEntry : depMap.entrySet()) {
+                  for (Map.Entry<SkyKey, ? extends NodeEntry> directDepEntry : depMap.entrySet()) {
                     NodeEntry dep = directDepEntry.getValue();
                     if (dep != null) {
                       if (dep.isDone() || !signalingDeps.contains(directDepEntry.getKey())) {
@@ -373,9 +378,8 @@
         InvalidationState state,
         DirtyKeyTracker dirtyKeyTracker,
         ForkJoinPool forkJoinPool,
-        boolean supportInterruptions,
-        ErrorHandler errorHandler) {
-      super(graph, invalidationReceiver, state, dirtyKeyTracker, forkJoinPool, errorHandler);
+        boolean supportInterruptions) {
+      super(graph, invalidationReceiver, state, dirtyKeyTracker, forkJoinPool);
       this.supportInterruptions = supportInterruptions;
     }
 
@@ -435,8 +439,16 @@
           pendingVisitations.add(Pair.of(key, invalidationType));
         }
       }
-      final Map<SkyKey, ? extends ThinNodeEntry> entries =
-          graph.getBatch(null, Reason.INVALIDATION, keysToGet);
+      final Map<SkyKey, ? extends ThinNodeEntry> entries;
+      try {
+        entries = graph.getBatch(null, Reason.INVALIDATION, keysToGet);
+      } catch (InterruptedException e) {
+        Thread.currentThread().interrupt();
+        // This can only happen if the main thread has been interrupted, and so the
+        // AbstractQueueVisitor is shutting down. We haven't yet removed the pending visitations, so
+        // we can resume next time.
+        return;
+      }
       if (enqueueingKeyForExistenceCheck != null && entries.size() != keysToGet.size()) {
         Set<SkyKey> missingKeys = Sets.difference(ImmutableSet.copyOf(keysToGet), entries.keySet());
         throw new IllegalStateException(
@@ -471,7 +483,16 @@
                 // method.
                 // Any exception thrown should be unrecoverable.
                 // This entry remains in the graph in this dirty state until it is re-evaluated.
-                MarkedDirtyResult markedDirtyResult = entry.markDirty(isChanged);
+                MarkedDirtyResult markedDirtyResult = null;
+                try {
+                  markedDirtyResult = entry.markDirty(isChanged);
+                } catch (InterruptedException e) {
+                  Thread.currentThread().interrupt();
+                  // This can only happen if the main thread has been interrupted, and so the
+                  // AbstractQueueVisitor is shutting down. We haven't yet removed the pending
+                  // visitation, so we can resume next time.
+                  return;
+                }
                 if (markedDirtyResult == null) {
                   // Another thread has already dirtied this node. Don't do anything in this thread.
                   if (supportInterruptions) {
diff --git a/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java
index cfbff0a..5c8236a 100644
--- a/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java
@@ -19,10 +19,8 @@
 import com.google.devtools.build.lib.collect.nestedset.NestedSetVisitor;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadHostile;
 import com.google.devtools.build.lib.events.EventHandler;
-
 import java.io.PrintStream;
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -118,7 +116,7 @@
    */
   @VisibleForTesting
   @Nullable
-  ErrorInfo getExistingErrorForTesting(SkyKey key);
+  ErrorInfo getExistingErrorForTesting(SkyKey key) throws InterruptedException;
 
   @Nullable
   NodeEntry getExistingEntryForTesting(SkyKey key);
diff --git a/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java
index 8b7b091..82df6fa 100644
--- a/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java
+++ b/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java
@@ -16,10 +16,8 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.util.GroupedList;
 import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper;
-
 import java.util.Collection;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -27,6 +25,9 @@
  *
  * <p>This interface is public only for the benefit of alternative graph implementations outside of
  * the package.
+ *
+ * <p>Certain graph implementations' node entries can throw {@link InterruptedException} on various
+ * accesses. Such exceptions should not be caught locally -- they should be allowed to propagate up.
  */
 public interface NodeEntry extends ThinNodeEntry {
   /**
@@ -81,7 +82,7 @@
    * this node is complete, i.e., after {@link #setValue} has been called.
    */
   @ThreadSafe
-  SkyValue getValue();
+  SkyValue getValue() throws InterruptedException;
 
   /**
    * Returns an immutable iterable of the direct deps of this node. This method may only be called
@@ -93,7 +94,7 @@
    * each call takes time proportional to the number of direct deps of the node.
    */
   @ThreadSafe
-  Iterable<SkyKey> getDirectDeps();
+  Iterable<SkyKey> getDirectDeps() throws InterruptedException;
 
   /** Removes a reverse dependency. */
   @ThreadSafe
@@ -123,21 +124,19 @@
    * <p>Use the static methods of {@link ValueWithMetadata} to extract metadata if necessary.
    */
   @ThreadSafe
-  SkyValue getValueMaybeWithMetadata();
+  SkyValue getValueMaybeWithMetadata() throws InterruptedException;
 
-  /**
-   * Returns the value, even if dirty or changed. Returns null otherwise.
-   */
+  /** Returns the value, even if dirty or changed. Returns null otherwise. */
   @ThreadSafe
-  SkyValue toValue();
+  SkyValue toValue() throws InterruptedException;
 
   /**
-   * Returns the error, if any, associated to this node. This method may only be called after
-   * the evaluation of this node is complete, i.e., after {@link #setValue} has been called.
+   * Returns the error, if any, associated to this node. This method may only be called after the
+   * evaluation of this node is complete, i.e., after {@link #setValue} has been called.
    */
   @Nullable
   @ThreadSafe
-  ErrorInfo getErrorInfo();
+  ErrorInfo getErrorInfo() throws InterruptedException;
 
   /**
    * Returns the set of reverse deps that have been declared so far this build. Only for use in
@@ -153,10 +152,9 @@
    * signaled.
    *
    * <p>This is an atomic operation to avoid a race where two threads work on two nodes, where one
-   * node depends on another (b depends on a). When a finishes, it signals <b>exactly</b> the set
-   * of reverse dependencies that are registered at the time of the {@code setValue} call. If b
-   * comes in before a, it is signaled (and re-scheduled) by a, otherwise it needs to do that
-   * itself.
+   * node depends on another (b depends on a). When a finishes, it signals <b>exactly</b> the set of
+   * reverse dependencies that are registered at the time of the {@code setValue} call. If b comes
+   * in before a, it is signaled (and re-scheduled) by a, otherwise it needs to do that itself.
    *
    * <p>{@code version} indicates the graph version at which this node is being written. If the
    * entry determines that the new value is equal to the previous value, the entry will keep its
@@ -164,7 +162,7 @@
    * changed.
    */
   @ThreadSafe
-  Set<SkyKey> setValue(SkyValue value, Version version);
+  Set<SkyKey> setValue(SkyValue value, Version version) throws InterruptedException;
 
   /**
    * Queries if the node is done and adds the given key as a reverse dependency. The return code
@@ -238,7 +236,7 @@
    * @return {@link Set} of reverse dependencies to signal that this node is done.
    */
   @ThreadSafe
-  Set<SkyKey> markClean();
+  Set<SkyKey> markClean() throws InterruptedException;
 
   /**
    * Forces this node to be re-evaluated, even if none of its dependencies are known to have
diff --git a/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
index 7353e54..834a614 100644
--- a/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
@@ -31,7 +31,6 @@
 import com.google.devtools.build.lib.collect.nestedset.NestedSetVisitor;
 import com.google.devtools.build.lib.concurrent.AbstractQueueVisitor;
 import com.google.devtools.build.lib.concurrent.ErrorClassifier;
-import com.google.devtools.build.lib.concurrent.ErrorHandler;
 import com.google.devtools.build.lib.concurrent.ForkJoinQuiescingExecutor;
 import com.google.devtools.build.lib.concurrent.QuiescingExecutor;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
@@ -132,7 +131,16 @@
 
     @Override
     public SkyValue get() {
-      return state.getValue();
+      try {
+        return state.getValue();
+      } catch (InterruptedException e) {
+        throw new IllegalStateException(
+            "Graph implementations in which value retrieval can block should not be used in "
+                + "frameworks that use the value in EvaluationProgressReceiver, since that could "
+                + "result in significant slowdowns: "
+                + state,
+            e);
+      }
     }
   }
 
@@ -157,7 +165,6 @@
   private final DirtyKeyTracker dirtyKeyTracker;
   private final Receiver<Collection<SkyKey>> inflightKeysReceiver;
   private final EventFilter storedEventFilter;
-  private final ErrorHandler errorHandler;
 
   public ParallelEvaluator(
       ProcessableGraph graph,
@@ -185,7 +192,6 @@
         new NestedSetVisitor<>(new NestedSetEventReceiver(reporter), emittedEventState);
     this.storedEventFilter = storedEventFilter;
     this.forkJoinPool = null;
-    this.errorHandler = ErrorHandler.NullHandler.INSTANCE;
   }
 
   public ParallelEvaluator(
@@ -200,8 +206,7 @@
       @Nullable EvaluationProgressReceiver progressReceiver,
       DirtyKeyTracker dirtyKeyTracker,
       Receiver<Collection<SkyKey>> inflightKeysReceiver,
-      ForkJoinPool forkJoinPool,
-      ErrorHandler errorHandler) {
+      ForkJoinPool forkJoinPool) {
     this.graph = graph;
     this.skyFunctions = skyFunctions;
     this.graphVersion = graphVersion;
@@ -217,13 +222,10 @@
         new NestedSetVisitor<>(new NestedSetEventReceiver(reporter), emittedEventState);
     this.storedEventFilter = storedEventFilter;
     this.forkJoinPool = Preconditions.checkNotNull(forkJoinPool);
-    this.errorHandler = errorHandler;
   }
 
-  private Map<SkyKey, NodeEntry> getBatchValues(
-      SkyKey parent,
-      Reason reason,
-      Iterable<SkyKey> keys) {
+  private Map<SkyKey, ? extends NodeEntry> getBatchValues(
+      SkyKey parent, Reason reason, Iterable<SkyKey> keys) throws InterruptedException {
     return graph.getBatch(parent, reason, keys);
   }
 
@@ -301,7 +303,8 @@
         };
 
     private SkyFunctionEnvironment(
-        SkyKey skyKey, GroupedList<SkyKey> directDeps, Set<SkyKey> oldDeps, ValueVisitor visitor) {
+        SkyKey skyKey, GroupedList<SkyKey> directDeps, Set<SkyKey> oldDeps, ValueVisitor visitor)
+        throws InterruptedException {
       this(skyKey, directDeps, null, oldDeps, visitor);
     }
 
@@ -310,7 +313,8 @@
         GroupedList<SkyKey> directDeps,
         @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo,
         Set<SkyKey> oldDeps,
-        ValueVisitor visitor) {
+        ValueVisitor visitor)
+        throws InterruptedException {
       this.skyKey = skyKey;
       this.oldDeps = oldDeps;
       this.directDeps = Collections.unmodifiableMap(batchPrefetch(
@@ -323,9 +327,13 @@
           skyKey);
     }
 
-    private Map<SkyKey, NodeEntry> batchPrefetch(
-        SkyKey requestor, GroupedList<SkyKey> depKeys, Set<SkyKey> oldDeps, boolean assertDone,
-        SkyKey keyForDebugging) {
+    private Map<SkyKey, ? extends NodeEntry> batchPrefetch(
+        SkyKey requestor,
+        GroupedList<SkyKey> depKeys,
+        Set<SkyKey> oldDeps,
+        boolean assertDone,
+        SkyKey keyForDebugging)
+        throws InterruptedException {
       Iterable<SkyKey> depKeysAsIterable = Iterables.concat(depKeys);
       Iterable<SkyKey> keysToPrefetch = depKeysAsIterable;
       if (PREFETCH_OLD_DEPS) {
@@ -333,10 +341,12 @@
         keysToPrefetchBuilder.addAll(depKeysAsIterable).addAll(oldDeps);
         keysToPrefetch = keysToPrefetchBuilder.build();
       }
-      Map<SkyKey, NodeEntry> batchMap = getBatchValues(requestor, Reason.PREFETCH, keysToPrefetch);
+      Map<SkyKey, ? extends NodeEntry> batchMap =
+          getBatchValues(requestor, Reason.PREFETCH, keysToPrefetch);
       if (PREFETCH_OLD_DEPS) {
-        batchMap = ImmutableMap.copyOf(
-            Maps.filterKeys(batchMap, Predicates.in(ImmutableSet.copyOf(depKeysAsIterable))));
+        batchMap =
+            ImmutableMap.<SkyKey, NodeEntry>copyOf(
+                Maps.filterKeys(batchMap, Predicates.in(ImmutableSet.copyOf(depKeysAsIterable))));
       }
       if (batchMap.size() != depKeys.numElements()) {
         throw new IllegalStateException(
@@ -346,7 +356,7 @@
                 + Sets.difference(depKeys.toSet(), batchMap.keySet()));
       }
       if (assertDone) {
-        for (Map.Entry<SkyKey, NodeEntry> entry : batchMap.entrySet()) {
+        for (Map.Entry<SkyKey, ? extends NodeEntry> entry : batchMap.entrySet()) {
           Preconditions.checkState(
               entry.getValue().isDone(), "%s had not done %s", keyForDebugging, entry);
         }
@@ -358,7 +368,8 @@
       Preconditions.checkState(building, skyKey);
     }
 
-    private NestedSet<TaggedEvents> buildEvents(NodeEntry entry, boolean missingChildren) {
+    private NestedSet<TaggedEvents> buildEvents(NodeEntry entry, boolean missingChildren)
+        throws InterruptedException {
       // Aggregate the nested set of events from the direct deps, also adding the events from
       // building this value.
       NestedSetBuilder<TaggedEvents> eventBuilder = NestedSetBuilder.stableOrder();
@@ -426,7 +437,8 @@
      * dependencies of this node <i>must</i> already have been registered, since this method may
      * register a dependence on the error transience node, which should always be the last dep.
      */
-    private void setError(NodeEntry state, ErrorInfo errorInfo, boolean isDirectlyTransient) {
+    private void setError(NodeEntry state, ErrorInfo errorInfo, boolean isDirectlyTransient)
+        throws InterruptedException {
       Preconditions.checkState(value == null, "%s %s %s", skyKey, value, errorInfo);
       Preconditions.checkState(this.errorInfo == null,
           "%s %s %s", skyKey, this.errorInfo, errorInfo);
@@ -454,7 +466,8 @@
         @Nullable SkyKey requestor,
         Iterable<SkyKey> keys,
         @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo,
-        int keySize) {
+        int keySize)
+        throws InterruptedException {
       ImmutableMap.Builder<SkyKey, SkyValue> builder = ImmutableMap.builder();
       ArrayList<SkyKey> missingKeys = new ArrayList<>(keySize);
       for (SkyKey key : keys) {
@@ -468,7 +481,7 @@
           missingKeys.add(key);
         }
       }
-      Map<SkyKey, NodeEntry> missingEntries =
+      Map<SkyKey, ? extends NodeEntry> missingEntries =
           getBatchValues(requestor, Reason.DEP_REQUESTED, missingKeys);
       for (SkyKey key : missingKeys) {
         builder.put(key, maybeGetValueFromError(key, missingEntries.get(key), bubbleErrorInfo));
@@ -477,8 +490,8 @@
     }
 
     @Override
-    protected Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(
-        Set<SkyKey> depKeys) {
+    protected Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(Set<SkyKey> depKeys)
+        throws InterruptedException {
       checkActive();
       Preconditions.checkState(
           !depKeys.contains(ErrorTransienceValue.KEY),
@@ -578,15 +591,20 @@
     }
 
     @Override
-    public <E1 extends Exception, E2 extends Exception, E3 extends Exception,
-            E4 extends Exception, E5 extends Exception>
+    public <
+            E1 extends Exception,
+            E2 extends Exception,
+            E3 extends Exception,
+            E4 extends Exception,
+            E5 extends Exception>
         Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValuesOrThrow(
             Iterable<SkyKey> depKeys,
             Class<E1> exceptionClass1,
             Class<E2> exceptionClass2,
             Class<E3> exceptionClass3,
             Class<E4> exceptionClass4,
-            Class<E5> exceptionClass5) {
+            Class<E5> exceptionClass5)
+            throws InterruptedException {
       newlyRequestedDeps.startGroup();
       Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> result = super.getValuesOrThrow(
           depKeys,
@@ -638,7 +656,7 @@
      * <p>The node entry is informed if the node's value and error are definitive via the flag
      * {@code completeValue}.
      */
-    void commit(NodeEntry primaryEntry, boolean enqueueParents) {
+    void commit(NodeEntry primaryEntry, boolean enqueueParents) throws InterruptedException {
       // Construct the definitive error info, if there is one.
       finalizeErrorInfo();
 
@@ -664,10 +682,8 @@
         // Remove the rdep on this entry for each of its old deps that is no longer a direct dep.
         Set<SkyKey> depsToRemove =
             Sets.difference(oldDeps, primaryEntry.getTemporaryDirectDeps().toSet());
-        Collection<NodeEntry> oldDepEntries = graph.getBatch(
-            skyKey,
-            Reason.RDEP_REMOVAL,
-            depsToRemove).values();
+        Collection<? extends NodeEntry> oldDepEntries =
+            graph.getBatch(skyKey, Reason.RDEP_REMOVAL, depsToRemove).values();
         for (NodeEntry oldDepEntry : oldDepEntries) {
           oldDepEntry.removeReverseDep(skyKey);
         }
@@ -754,7 +770,7 @@
 
     private ValueVisitor(ForkJoinPool forkJoinPool) {
       quiescingExecutor =
-          new ForkJoinQuiescingExecutor(forkJoinPool, VALUE_VISITOR_ERROR_CLASSIFIER, errorHandler);
+          new ForkJoinQuiescingExecutor(forkJoinPool, VALUE_VISITOR_ERROR_CLASSIFIER);
     }
 
     private ValueVisitor(int threadCount) {
@@ -766,8 +782,7 @@
               TimeUnit.SECONDS,
               /*failFastOnException*/ true,
               "skyframe-evaluator",
-              VALUE_VISITOR_ERROR_CLASSIFIER,
-              errorHandler);
+              VALUE_VISITOR_ERROR_CLASSIFIER);
     }
 
     private void waitForCompletion() throws InterruptedException {
@@ -884,14 +899,15 @@
      * Returns true if this depGroup consists of the error transience value and the error transience
      * value is newer than the entry, meaning that the entry must be re-evaluated.
      */
-    private boolean invalidatedByErrorTransience(Collection<SkyKey> depGroup, NodeEntry entry) {
+    private boolean invalidatedByErrorTransience(Collection<SkyKey> depGroup, NodeEntry entry)
+        throws InterruptedException {
       return depGroup.size() == 1
           && depGroup.contains(ErrorTransienceValue.KEY)
           && !graph.get(
               null, Reason.OTHER, ErrorTransienceValue.KEY).getVersion().atMost(entry.getVersion());
     }
 
-    private DirtyOutcome maybeHandleDirtyNode(NodeEntry state) {
+    private DirtyOutcome maybeHandleDirtyNode(NodeEntry state) throws InterruptedException {
       if (!state.isDirty()) {
         return DirtyOutcome.NEEDS_EVALUATION;
       }
@@ -934,9 +950,9 @@
             // is done, then it is the parent's responsibility to notice that, which we do here.
             // We check the deps for errors so that we don't continue building this node if it has
             // a child error.
-            Map<SkyKey, NodeEntry> entriesToCheck =
+            Map<SkyKey, ? extends NodeEntry> entriesToCheck =
                 graph.getBatch(skyKey, Reason.OTHER, directDepsToCheck);
-            for (Map.Entry<SkyKey, NodeEntry> entry : entriesToCheck.entrySet()) {
+            for (Entry<SkyKey, ? extends NodeEntry> entry : entriesToCheck.entrySet()) {
               if (entry.getValue().isDone() && entry.getValue().getErrorInfo() != null) {
                 // If any child has an error, we arbitrarily add a dep on the first one (needed
                 // for error bubbling) and throw an exception coming from it.
@@ -945,7 +961,7 @@
                 state.addTemporaryDirectDeps(GroupedListHelper.create(ImmutableList.of(errorKey)));
                 errorEntry.checkIfDoneForDirtyReverseDep(skyKey);
                 // Perform the necessary bookkeeping for any deps that are not being used.
-                for (Map.Entry<SkyKey, NodeEntry> depEntry : entriesToCheck.entrySet()) {
+                for (Entry<SkyKey, ? extends NodeEntry> depEntry : entriesToCheck.entrySet()) {
                   if (!depEntry.getKey().equals(errorKey)) {
                     depEntry.getValue().removeReverseDep(skyKey);
                   }
@@ -969,8 +985,10 @@
 
           // TODO(bazel-team): If this signals the current node, consider falling through to the
           // VERIFIED_CLEAN case below directly, without scheduling a new Evaluate().
-          for (Map.Entry<SkyKey, NodeEntry> e : graph.createIfAbsentBatch(
-              skyKey, Reason.ENQUEUING_CHILD, directDepsToCheck).entrySet()) {
+          for (Map.Entry<SkyKey, ? extends NodeEntry> e :
+              graph
+                  .createIfAbsentBatch(skyKey, Reason.ENQUEUING_CHILD, directDepsToCheck)
+                  .entrySet()) {
             SkyKey directDep = e.getKey();
             NodeEntry directDepEntry = e.getValue();
             enqueueChild(skyKey, state, directDep, directDepEntry, /*depAlreadyExists=*/ true);
@@ -1005,6 +1023,7 @@
 
     @Override
     public void run() {
+      try {
       NodeEntry state = Preconditions.checkNotNull(
           graph.get(null, Reason.EVALUATION, skyKey),
           skyKey);
@@ -1047,8 +1066,8 @@
             }
           }
 
-          Map<SkyKey, NodeEntry> newlyRequestedDeps =
-              getBatchValues(skyKey, Reason.RDEP_ADDITION, env.newlyRequestedDeps);
+            Map<SkyKey, ? extends NodeEntry> newlyRequestedDeps =
+                getBatchValues(skyKey, Reason.RDEP_ADDITION, env.newlyRequestedDeps);
           boolean isTransitivelyTransient = reifiedBuilderException.isTransient();
           for (NodeEntry depEntry
               : Iterables.concat(env.directDeps.values(), newlyRequestedDeps.values())) {
@@ -1073,11 +1092,6 @@
           }
           throw SchedulerException.ofError(errorInfo, skyKey);
         }
-      } catch (InterruptedException ie) {
-        // InterruptedException cannot be thrown by Runnable.run, so we must wrap it.
-        // Interrupts can be caught by both the Evaluator and the AbstractQueueVisitor.
-        // The former will unwrap the IE and propagate it as is; the latter will throw a new IE.
-        throw SchedulerException.ofInterruption(ie, skyKey);
       } catch (RuntimeException re) {
         // Programmer error (most likely NPE or a failed precondition in a SkyFunction). Output
         // some context together with the exception.
@@ -1127,24 +1141,24 @@
             skyKey,
             state,
             childErrorKey);
-        if (newDirectDeps.contains(childErrorKey)) {
-          // Add this dep if it was just requested. In certain rare race conditions (see
-          // MemoizingEvaluatorTest.cachedErrorCausesRestart) this dep may have already been
-          // requested.
-          state.addTemporaryDirectDeps(GroupedListHelper.create(ImmutableList.of(childErrorKey)));
-          DependencyState childErrorState;
-          if (oldDeps.contains(childErrorKey)) {
-            childErrorState = childErrorEntry.checkIfDoneForDirtyReverseDep(skyKey);
-          } else {
-            childErrorState = childErrorEntry.addReverseDepAndCheckIfDone(skyKey);
-          }
-          Preconditions.checkState(
-              childErrorState == DependencyState.DONE,
-              "skyKey: %s, state: %s childErrorKey: %s",
-              skyKey,
-              state,
-              childErrorKey,
-              childErrorEntry);
+          if (newDirectDeps.contains(childErrorKey)) {
+            // Add this dep if it was just requested. In certain rare race conditions (see
+            // MemoizingEvaluatorTest.cachedErrorCausesRestart) this dep may have already been
+            // requested.
+            state.addTemporaryDirectDeps(GroupedListHelper.create(ImmutableList.of(childErrorKey)));
+            DependencyState childErrorState;
+            if (oldDeps.contains(childErrorKey)) {
+              childErrorState = childErrorEntry.checkIfDoneForDirtyReverseDep(skyKey);
+            } else {
+              childErrorState = childErrorEntry.addReverseDepAndCheckIfDone(skyKey);
+            }
+            Preconditions.checkState(
+                childErrorState == DependencyState.DONE,
+                "skyKey: %s, state: %s childErrorKey: %s",
+                skyKey,
+                state,
+                childErrorKey,
+                childErrorEntry);
         }
         ErrorInfo childErrorInfo = Preconditions.checkNotNull(childErrorEntry.getErrorInfo());
         visitor.preventNewEvaluations();
@@ -1180,8 +1194,8 @@
         return;
       }
 
-      for (Map.Entry<SkyKey, NodeEntry> e
-          : graph.createIfAbsentBatch(skyKey, Reason.ENQUEUING_CHILD, newDirectDeps).entrySet()) {
+        for (Entry<SkyKey, ? extends NodeEntry> e :
+            graph.createIfAbsentBatch(skyKey, Reason.ENQUEUING_CHILD, newDirectDeps).entrySet()) {
         SkyKey newDirectDep = e.getKey();
         NodeEntry newDirectDepEntry = e.getValue();
         enqueueChild(
@@ -1191,6 +1205,12 @@
             newDirectDepEntry,
             /*depAlreadyExists=*/ oldDeps.contains(newDirectDep));
       }
+      } catch (InterruptedException ie) {
+        // InterruptedException cannot be thrown by Runnable.run, so we must wrap it.
+        // Interrupts can be caught by both the Evaluator and the AbstractQueueVisitor.
+        // The former will unwrap the IE and propagate it as is; the latter will throw a new IE.
+        throw SchedulerException.ofInterruption(ie, skyKey);
+      }
       // It is critical that there is no code below this point.
     }
 
@@ -1219,17 +1239,16 @@
 
   /**
    * Signals all parents that this node is finished. If visitor is not null, also enqueues any
-   * parents that are ready. If visitor is null, indicating that we are building this node after
-   * the main build aborted, then skip any parents that are already done (that can happen with
-   * cycles).
+   * parents that are ready. If visitor is null, indicating that we are building this node after the
+   * main build aborted, then skip any parents that are already done (that can happen with cycles).
    */
   private void signalValuesAndEnqueueIfReady(
-      @Nullable ValueVisitor visitor, SkyKey skyKey, Iterable<SkyKey> keys, Version version) {
+      @Nullable ValueVisitor visitor, SkyKey skyKey, Iterable<SkyKey> keys, Version version)
+      throws InterruptedException {
     // No fields of the entry are needed here, since we're just enqueuing for evaluation, but more
     // importantly, these hints are not respected for not-done nodes. If they are, we may need to
     // alter this hint.
-    Map<SkyKey, NodeEntry> batch =
-        graph.getBatch(skyKey, Reason.SIGNAL_DEP, keys);
+    Map<SkyKey, ? extends NodeEntry> batch = graph.getBatch(skyKey, Reason.SIGNAL_DEP, keys);
     if (visitor != null) {
       for (SkyKey key : keys) {
         NodeEntry entry = Preconditions.checkNotNull(batch.get(key), key);
@@ -1252,7 +1271,8 @@
    * If child is not done, removes {@param inProgressParent} from {@param child}'s reverse deps.
    * Returns whether child should be removed from inProgressParent's entry's direct deps.
    */
-  private boolean removeIncompleteChildForCycle(SkyKey inProgressParent, SkyKey child) {
+  private boolean removeIncompleteChildForCycle(SkyKey inProgressParent, SkyKey child)
+      throws InterruptedException {
     NodeEntry childEntry = graph.get(inProgressParent, Reason.CYCLE_CHECKING, child);
     if (!isDoneForBuild(childEntry)) {
       childEntry.removeInProgressReverseDep(inProgressParent);
@@ -1272,7 +1292,7 @@
   private static void registerNewlyDiscoveredDepsForDoneEntry(
       SkyKey skyKey,
       NodeEntry entry,
-      Map<SkyKey, NodeEntry> newlyRequestedDepMap,
+      Map<SkyKey, ? extends NodeEntry> newlyRequestedDepMap,
       Set<SkyKey> oldDeps,
       SkyFunctionEnvironment env) {
     Set<SkyKey> unfinishedDeps = new HashSet<>();
@@ -1300,7 +1320,8 @@
     Preconditions.checkState(entry.isReady(), "%s %s %s", skyKey, entry, env.newlyRequestedDeps);
   }
 
-  private void informProgressReceiverThatValueIsDone(SkyKey key, NodeEntry entry) {
+  private void informProgressReceiverThatValueIsDone(SkyKey key, NodeEntry entry)
+      throws InterruptedException {
     if (progressReceiver != null) {
       Preconditions.checkState(entry.isDone(), entry);
       SkyValue value = entry.getValue();
@@ -1327,7 +1348,8 @@
     // directly without launching the heavy machinery, spawning threads, etc.
     // Inform progressReceiver that these nodes are done to be consistent with the main code path.
     boolean allAreDone = true;
-    Map<SkyKey, NodeEntry> batch = getBatchValues(null, Reason.PRE_OR_POST_EVALUATION, skyKeySet);
+    Map<SkyKey, ? extends NodeEntry> batch =
+        getBatchValues(null, Reason.PRE_OR_POST_EVALUATION, skyKeySet);
     for (SkyKey key : skyKeySet) {
       if (!isDoneForBuild(batch.get(key))) {
         allAreDone = false;
@@ -1401,8 +1423,8 @@
           graph,
           dirtyKeyTracker);
     }
-    for (Map.Entry<SkyKey, NodeEntry> e
-        : graph.createIfAbsentBatch(null, Reason.PRE_OR_POST_EVALUATION, skyKeys).entrySet()) {
+    for (Entry<SkyKey, ? extends NodeEntry> e :
+        graph.createIfAbsentBatch(null, Reason.PRE_OR_POST_EVALUATION, skyKeys).entrySet()) {
       SkyKey skyKey = e.getKey();
       NodeEntry entry = e.getValue();
       // This must be equivalent to the code in enqueueChild above, in order to be thread-safe.
@@ -1477,23 +1499,31 @@
   }
 
   /**
-   * Walk up graph to find a top-level node (without parents) that wanted this failure. Store
-   * the failed nodes along the way in a map, with ErrorInfos that are appropriate for that layer.
+   * Walk up graph to find a top-level node (without parents) that wanted this failure. Store the
+   * failed nodes along the way in a map, with ErrorInfos that are appropriate for that layer.
    * Example:
+   *
+   * <pre>
    *                      foo   bar
    *                        \   /
    *           unrequested   baz
    *                     \    |
    *                      failed-node
+   * </pre>
+   *
    * User requests foo, bar. When failed-node fails, we look at its parents. unrequested is not
    * in-flight, so we replace failed-node by baz and repeat. We look at baz's parents. foo is
-   * in-flight, so we replace baz by foo. Since foo is a top-level node and doesn't have parents,
-   * we then break, since we know a top-level node, foo, that depended on the failed node.
+   * in-flight, so we replace baz by foo. Since foo is a top-level node and doesn't have parents, we
+   * then break, since we know a top-level node, foo, that depended on the failed node.
    *
-   * There's the potential for a weird "track jump" here in the case:
+   * <p>There's the potential for a weird "track jump" here in the case:
+   *
+   * <pre>
    *                        foo
    *                       / \
    *                   fail1 fail2
+   * </pre>
+   *
    * If fail1 and fail2 fail simultaneously, fail2 may start propagating up in the loop below.
    * However, foo requests fail1 first, and then throws an exception based on that. This is not
    * incorrect, but may be unexpected.
@@ -1506,8 +1536,9 @@
    * <p>Note that we are not propagating error to the first top-level node but to the highest one,
    * because during this process we can add useful information about error from other nodes.
    */
-  private Map<SkyKey, ValueWithMetadata> bubbleErrorUp(final ErrorInfo leafFailure,
-      SkyKey errorKey, Iterable<SkyKey> skyKeys, ValueVisitor visitor) {
+  private Map<SkyKey, ValueWithMetadata> bubbleErrorUp(
+      final ErrorInfo leafFailure, SkyKey errorKey, Iterable<SkyKey> skyKeys, ValueVisitor visitor)
+      throws InterruptedException {
     Set<SkyKey> rootValues = ImmutableSet.copyOf(skyKeys);
     ErrorInfo error = leafFailure;
     Map<SkyKey, ValueWithMetadata> bubbleErrorInfo = new HashMap<>();
@@ -1651,9 +1682,9 @@
   }
 
   /**
-   * Constructs an {@link EvaluationResult} from the {@link #graph}.  Looks for cycles if there
-   * are unfinished nodes but no error was already found through bubbling up
-   * (as indicated by {@code bubbleErrorInfo} being null).
+   * Constructs an {@link EvaluationResult} from the {@link #graph}. Looks for cycles if there are
+   * unfinished nodes but no error was already found through bubbling up (as indicated by {@code
+   * bubbleErrorInfo} being null).
    *
    * <p>{@code visitor} may be null, but only in the case where all graph entries corresponding to
    * {@code skyKeys} are known to be in the DONE state ({@code entry.isDone()} returns true).
@@ -1662,7 +1693,8 @@
       @Nullable ValueVisitor visitor,
       Iterable<SkyKey> skyKeys,
       @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo,
-      boolean catastrophe) {
+      boolean catastrophe)
+      throws InterruptedException {
     Preconditions.checkState(
         catastrophe == (keepGoing && bubbleErrorInfo != null),
         "Catastrophe not consistent with keepGoing mode and bubbleErrorInfo: %s %s %s %s",
@@ -1739,8 +1771,11 @@
   }
 
   private <T extends SkyValue> void checkForCycles(
-      Iterable<SkyKey> badRoots, EvaluationResult.Builder<T> result, final ValueVisitor visitor,
-      boolean keepGoing) {
+      Iterable<SkyKey> badRoots,
+      EvaluationResult.Builder<T> result,
+      final ValueVisitor visitor,
+      boolean keepGoing)
+      throws InterruptedException {
     try (AutoProfiler p = AutoProfiler.logged("Checking for Skyframe cycles", LOG, 10)) {
       for (SkyKey root : badRoots) {
         ErrorInfo errorInfo = checkForCycles(root, visitor, keepGoing);
@@ -1774,13 +1809,13 @@
   /**
    * The algorithm for this cycle detector is as follows. We visit the graph depth-first, keeping
    * track of the path we are currently on. We skip any DONE nodes (they are transitively
-   * error-free). If we come to a node already on the path, we immediately construct a cycle. If
-   * we are in the noKeepGoing case, we return ErrorInfo with that cycle to the caller. Otherwise,
-   * we continue. Once all of a node's children are done, we construct an error value for it, based
-   * on those children. Finally, when the original root's node is constructed, we return its
-   * ErrorInfo.
+   * error-free). If we come to a node already on the path, we immediately construct a cycle. If we
+   * are in the noKeepGoing case, we return ErrorInfo with that cycle to the caller. Otherwise, we
+   * continue. Once all of a node's children are done, we construct an error value for it, based on
+   * those children. Finally, when the original root's node is constructed, we return its ErrorInfo.
    */
-  private ErrorInfo checkForCycles(SkyKey root, ValueVisitor visitor, boolean keepGoing) {
+  private ErrorInfo checkForCycles(SkyKey root, ValueVisitor visitor, boolean keepGoing)
+      throws InterruptedException {
     // The number of cycles found. Do not keep on searching for more cycles after this many were
     // found.
     int cyclesFound = 0;
@@ -1926,7 +1961,7 @@
       // out.
       // TODO(janakr): If graph implementations start using these hints for not-done nodes, we may
       // have to change this.
-      Map<SkyKey, NodeEntry> childrenNodes =
+      Map<SkyKey, ? extends NodeEntry> childrenNodes =
           graph.getBatch(key, Reason.EXISTENCE_CHECKING, children);
       Preconditions.checkState(childrenNodes.size() == Iterables.size(children), childrenNodes);
       children = Maps.filterValues(childrenNodes, new Predicate<NodeEntry>() {
@@ -1962,7 +1997,8 @@
    * @param children child nodes to query for errors.
    * @return List of ErrorInfos from all children that had errors.
    */
-  private List<ErrorInfo> getChildrenErrorsForCycle(SkyKey parent, Iterable<SkyKey> children) {
+  private List<ErrorInfo> getChildrenErrorsForCycle(SkyKey parent, Iterable<SkyKey> children)
+      throws InterruptedException {
     List<ErrorInfo> allErrors = new ArrayList<>();
     boolean foundCycle = false;
     for (NodeEntry childNode : getAndCheckDoneBatchForCycle(parent, children).values()) {
@@ -1984,11 +2020,11 @@
    * @return List of ErrorInfos from all children that had errors.
    */
   private List<ErrorInfo> getChildrenErrorsForCycleChecking(
-      Iterable<SkyKey> children, SkyKey unfinishedChild) {
+      Iterable<SkyKey> children, SkyKey unfinishedChild) throws InterruptedException {
     List<ErrorInfo> allErrors = new ArrayList<>();
-    Set<Entry<SkyKey, NodeEntry>> childEntries =
+    Set<? extends Entry<SkyKey, ? extends NodeEntry>> childEntries =
         getBatchValues(null, Reason.CYCLE_CHECKING, children).entrySet();
-    for (Entry<SkyKey, NodeEntry> childMapEntry : childEntries) {
+    for (Entry<SkyKey, ? extends NodeEntry> childMapEntry : childEntries) {
       SkyKey childKey = childMapEntry.getKey();
       NodeEntry childNodeEntry = childMapEntry.getValue();
       ErrorInfo errorInfo = getErrorMaybe(childKey, childNodeEntry,
@@ -2001,7 +2037,8 @@
   }
 
   @Nullable
-  private ErrorInfo getErrorMaybe(SkyKey key, NodeEntry childNodeEntry, boolean allowUnfinished) {
+  private static ErrorInfo getErrorMaybe(
+      SkyKey key, NodeEntry childNodeEntry, boolean allowUnfinished) throws InterruptedException {
     Preconditions.checkNotNull(childNodeEntry, key);
     if (!allowUnfinished) {
       return checkDone(key, childNodeEntry).getErrorInfo();
@@ -2027,7 +2064,8 @@
       NodeEntry entry,
       @Nullable SkyKey cycleChild,
       Iterable<SkyKey> toVisit,
-      int cycleLength) {
+      int cycleLength)
+      throws InterruptedException {
     GroupedList<SkyKey> directDeps = entry.getTemporaryDirectDeps();
     Set<SkyKey> unvisitedDeps = Sets.newHashSetWithExpectedSize(directDeps.numElements());
     Iterables.addAll(unvisitedDeps, Iterables.concat(directDeps));
@@ -2069,7 +2107,7 @@
   }
 
   private Set<SkyKey> removeIncompleteChildrenForCycle(
-      SkyKey key, NodeEntry entry, Iterable<SkyKey> children) {
+      SkyKey key, NodeEntry entry, Iterable<SkyKey> children) throws InterruptedException {
     Set<SkyKey> unfinishedDeps = new HashSet<>();
     for (SkyKey child : children) {
       if (removeIncompleteChildForCycle(key, child)) {
@@ -2086,14 +2124,14 @@
     return entry;
   }
 
-  private NodeEntry getAndCheckDoneForCycle(SkyKey key) {
+  private NodeEntry getAndCheckDoneForCycle(SkyKey key) throws InterruptedException {
     return checkDone(key, graph.get(null, Reason.CYCLE_CHECKING, key));
   }
 
-  private Map<SkyKey, NodeEntry> getAndCheckDoneBatchForCycle(
-      SkyKey parent, Iterable<SkyKey> keys) {
-    Map<SkyKey, NodeEntry> nodes = getBatchValues(parent, Reason.CYCLE_CHECKING, keys);
-    for (Map.Entry<SkyKey, NodeEntry> nodeEntryMapEntry : nodes.entrySet()) {
+  private Map<SkyKey, ? extends NodeEntry> getAndCheckDoneBatchForCycle(
+      SkyKey parent, Iterable<SkyKey> keys) throws InterruptedException {
+    Map<SkyKey, ? extends NodeEntry> nodes = getBatchValues(parent, Reason.CYCLE_CHECKING, keys);
+    for (Entry<SkyKey, ? extends NodeEntry> nodeEntryMapEntry : nodes.entrySet()) {
       checkDone(nodeEntryMapEntry.getKey(), nodeEntryMapEntry.getValue());
     }
     return nodes;
@@ -2104,7 +2142,8 @@
   private static SkyValue maybeGetValueFromError(
       SkyKey key,
       @Nullable NodeEntry entry,
-      @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo) {
+      @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo)
+      throws InterruptedException {
     SkyValue value = bubbleErrorInfo == null ? null : bubbleErrorInfo.get(key);
     if (value != null) {
       Preconditions.checkNotNull(
@@ -2127,8 +2166,9 @@
       Map<SkyKey, SkyValue> injectionMap,
       Version version,
       EvaluableGraph graph,
-      DirtyKeyTracker dirtyKeyTracker) {
-    Map<SkyKey, NodeEntry> prevNodeEntries =
+      DirtyKeyTracker dirtyKeyTracker)
+      throws InterruptedException {
+    Map<SkyKey, ? extends NodeEntry> prevNodeEntries =
         graph.createIfAbsentBatch(null, Reason.OTHER, injectionMap.keySet());
     for (Map.Entry<SkyKey, SkyValue> injectionEntry : injectionMap.entrySet()) {
       SkyKey key = injectionEntry.getKey();
diff --git a/src/main/java/com/google/devtools/build/skyframe/QueryableGraph.java b/src/main/java/com/google/devtools/build/skyframe/QueryableGraph.java
index f76c0ae..0286844 100644
--- a/src/main/java/com/google/devtools/build/skyframe/QueryableGraph.java
+++ b/src/main/java/com/google/devtools/build/skyframe/QueryableGraph.java
@@ -15,10 +15,15 @@
 
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
-/** A graph that exposes its entries and structure, for use by classes that must traverse it. */
+/**
+ * A graph that exposes its entries and structure, for use by classes that must traverse it.
+ *
+ * <p>Certain graph implementations can throw {@link InterruptedException} when trying to retrieve
+ * node entries. Such exceptions should not be caught locally -- they should be allowed to propagate
+ * up.
+ */
 @ThreadSafe
 public interface QueryableGraph {
   /**
@@ -29,18 +34,19 @@
    * @param reason the reason the node is being requested.
    */
   @Nullable
-  NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key);
+  NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key) throws InterruptedException;
 
   /**
    * Fetches all the given nodes. Returns a map {@code m} such that, for all {@code k} in {@code
    * keys}, {@code m.get(k).equals(e)} iff {@code get(k) == e} and {@code e != null}, and {@code
    * !m.containsKey(k)} iff {@code get(k) == null}.
-   * 
+   *
    * @param requestor if non-{@code null}, the node on behalf of which the given {@code keys} are
    *     being requested.
    * @param reason the reason the nodes are being requested.
    */
-  Map<SkyKey, NodeEntry> getBatch(@Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys);
+  Map<SkyKey, ? extends NodeEntry> getBatch(
+      @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) throws InterruptedException;
 
   /**
    * The reason that a node is being looked up in the Skyframe graph.
diff --git a/src/main/java/com/google/devtools/build/skyframe/QueryableGraphBackedSkyFunctionEnvironment.java b/src/main/java/com/google/devtools/build/skyframe/QueryableGraphBackedSkyFunctionEnvironment.java
index 79ed640..ef96167 100644
--- a/src/main/java/com/google/devtools/build/skyframe/QueryableGraphBackedSkyFunctionEnvironment.java
+++ b/src/main/java/com/google/devtools/build/skyframe/QueryableGraphBackedSkyFunctionEnvironment.java
@@ -13,19 +13,14 @@
 // limitations under the License.
 package com.google.devtools.build.skyframe;
 
-import com.google.common.base.Function;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.skyframe.QueryableGraph.Reason;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
-import javax.annotation.Nullable;
-
 /**
  * A {@link SkyFunction.Environment} backed by a {@link QueryableGraph}. For use when a single
  * SkyFunction needs recomputation, and its dependencies do not need to be evaluated. Any missing
@@ -41,41 +36,40 @@
     this.eventHandler = eventHandler;
   }
 
-  private static final Function<NodeEntry, ValueOrUntypedException> NODE_ENTRY_TO_UNTYPED_VALUE =
-      new Function<NodeEntry, ValueOrUntypedException>() {
-        @Override
-        public ValueOrUntypedException apply(@Nullable NodeEntry nodeEntry) {
-          if (nodeEntry == null || !nodeEntry.isDone()) {
-            return ValueOrExceptionUtils.ofNull();
-          }
-          SkyValue maybeWrappedValue = nodeEntry.getValueMaybeWithMetadata();
-          SkyValue justValue = ValueWithMetadata.justValue(maybeWrappedValue);
-          if (justValue != null) {
-            return ValueOrExceptionUtils.ofValueUntyped(justValue);
-          }
-          ErrorInfo errorInfo =
-              Preconditions.checkNotNull(ValueWithMetadata.getMaybeErrorInfo(maybeWrappedValue));
-          Exception exception = errorInfo.getException();
+  private static ValueOrUntypedException toUntypedValue(NodeEntry nodeEntry)
+      throws InterruptedException {
+    if (nodeEntry == null || !nodeEntry.isDone()) {
+      return ValueOrExceptionUtils.ofNull();
+    }
+    SkyValue maybeWrappedValue = nodeEntry.getValueMaybeWithMetadata();
+    SkyValue justValue = ValueWithMetadata.justValue(maybeWrappedValue);
+    if (justValue != null) {
+      return ValueOrExceptionUtils.ofValueUntyped(justValue);
+    }
+    ErrorInfo errorInfo =
+        Preconditions.checkNotNull(ValueWithMetadata.getMaybeErrorInfo(maybeWrappedValue));
+    Exception exception = errorInfo.getException();
 
-          if (exception != null) {
-            // Give SkyFunction#compute a chance to handle this exception.
-            return ValueOrExceptionUtils.ofExn(exception);
-          }
-          // In a cycle.
-          Preconditions.checkState(
-              !Iterables.isEmpty(errorInfo.getCycleInfo()), "%s %s", errorInfo, maybeWrappedValue);
-          return ValueOrExceptionUtils.ofNull();
-        }
-      };
+    if (exception != null) {
+      // Give SkyFunction#compute a chance to handle this exception.
+      return ValueOrExceptionUtils.ofExn(exception);
+    }
+    // In a cycle.
+    Preconditions.checkState(
+        !Iterables.isEmpty(errorInfo.getCycleInfo()), "%s %s", errorInfo, maybeWrappedValue);
+    return ValueOrExceptionUtils.ofNull();
+  }
 
   @Override
-  protected Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(Set<SkyKey> depKeys) {
-    Map<SkyKey, NodeEntry> resultMap = queryableGraph.getBatch(null, Reason.DEP_REQUESTED, depKeys);
-    Map<SkyKey, NodeEntry> resultWithMissingKeys = new HashMap<>(resultMap);
-    for (SkyKey missingDep : Sets.difference(depKeys, resultMap.keySet())) {
-      resultWithMissingKeys.put(missingDep, null);
+  protected Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(Set<SkyKey> depKeys)
+      throws InterruptedException {
+    Map<SkyKey, ? extends NodeEntry> resultMap =
+        queryableGraph.getBatch(null, Reason.DEP_REQUESTED, depKeys);
+    Map<SkyKey, ValueOrUntypedException> result = Maps.newHashMapWithExpectedSize(depKeys.size());
+    for (SkyKey dep : depKeys) {
+      result.put(dep, toUntypedValue(resultMap.get(dep)));
     }
-    return Maps.transformValues(resultWithMissingKeys, NODE_ENTRY_TO_UNTYPED_VALUE);
+    return result;
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java b/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java
index c65f681..905c25f 100644
--- a/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java
+++ b/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java
@@ -16,7 +16,6 @@
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.common.options.OptionsClassProvider;
-
 import javax.annotation.Nullable;
 
 /**
@@ -60,7 +59,7 @@
 
   @Nullable
   @Override
-  public ErrorInfo getExistingErrorForTesting(SkyKey key) {
+  public ErrorInfo getExistingErrorForTesting(SkyKey key) throws InterruptedException {
     return memoizingEvaluator.getExistingErrorForTesting(key);
   }
 
diff --git a/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java b/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java
index 637c202..6bd52c6 100644
--- a/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java
+++ b/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java
@@ -16,9 +16,7 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.events.EventHandler;
-
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
@@ -67,56 +65,83 @@
   String extractTag(SkyKey skyKey);
 
   /**
-   * The services provided to the {@link SkyFunction} implementation by the graph implementation.
+   * The services provided to the {@link SkyFunction#compute} implementation by the Skyframe
+   * evaluation framework.
    */
   interface Environment {
     /**
      * Returns a direct dependency. If the specified value is not in the set of already evaluated
-     * direct dependencies, returns {@code null}. Also returns {@code null} if the specified
-     * value has already been evaluated and found to be in error.
+     * direct dependencies, returns {@code null}. Also returns {@code null} if the specified value
+     * has already been evaluated and found to be in error.
      *
      * <p>On a subsequent evaluation, if any of this value's dependencies have changed they will be
-     * re-evaluated in the same order as originally requested by the {@code SkyFunction} using
-     * this {@code getValue} call (see {@link #getValues} for when preserving the order is not
+     * re-evaluated in the same order as originally requested by the {@code SkyFunction} using this
+     * {@code getValue} call (see {@link #getValues} for when preserving the order is not
      * important).
+     *
+     * <p>This method and the ones below may throw {@link InterruptedException}. Such exceptions
+     * must not be caught by the {@link SkyFunction#compute} implementation. Instead, they should be
+     * propagated up to the caller of {@link SkyFunction#compute}.
      */
     @Nullable
-    SkyValue getValue(SkyKey valueName);
+    SkyValue getValue(SkyKey valueName) throws InterruptedException;
 
     /**
      * Returns a direct dependency. If the specified value is not in the set of already evaluated
-     * direct dependencies, returns {@code null}. If the specified value has already been
-     * evaluated and found to be in error, throws the exception coming from the error, so long as
-     * the exception is of one of the specified types. SkyFunction implementations may use this
-     * method to continue evaluation even if one of their dependencies is in error by catching
-     * the thrown exception and proceeding. The caller must specify the exception type(s) that
-     * might be thrown using the {@code exceptionClass} argument(s). If the dependency's
-     * exception is not an instance of {@code exceptionClass}, {@code null} is returned.
+     * direct dependencies, returns {@code null}. If the specified value has already been evaluated
+     * and found to be in error, throws the exception coming from the error, so long as the
+     * exception is of one of the specified types. SkyFunction implementations may use this method
+     * to continue evaluation even if one of their dependencies is in error by catching the thrown
+     * exception and proceeding. The caller must specify the exception type(s) that might be thrown
+     * using the {@code exceptionClass} argument(s). If the dependency's exception is not an
+     * instance of {@code exceptionClass}, {@code null} is returned.
      *
      * <p>The exception class given cannot be a supertype or a subtype of {@link RuntimeException},
-     * or a subtype of {@link InterruptedException}. See
-     * {@link SkyFunctionException#validateExceptionType} for details.
+     * or a subtype of {@link InterruptedException}. See {@link
+     * SkyFunctionException#validateExceptionType} for details.
      */
     @Nullable
-    <E extends Exception> SkyValue getValueOrThrow(SkyKey depKey, Class<E> exceptionClass) throws E;
+    <E extends Exception> SkyValue getValueOrThrow(SkyKey depKey, Class<E> exceptionClass)
+        throws E, InterruptedException;
+
     @Nullable
-    <E1 extends Exception, E2 extends Exception> SkyValue getValueOrThrow(SkyKey depKey,
-        Class<E1> exceptionClass1, Class<E2> exceptionClass2) throws E1, E2;
+    <E1 extends Exception, E2 extends Exception> SkyValue getValueOrThrow(
+        SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2)
+        throws E1, E2, InterruptedException;
+
     @Nullable
     <E1 extends Exception, E2 extends Exception, E3 extends Exception> SkyValue getValueOrThrow(
-        SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2,
-        Class<E3> exceptionClass3) throws E1, E2, E3;
+        SkyKey depKey,
+        Class<E1> exceptionClass1,
+        Class<E2> exceptionClass2,
+        Class<E3> exceptionClass3)
+        throws E1, E2, E3, InterruptedException;
+
     @Nullable
     <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception>
-        SkyValue getValueOrThrow(SkyKey depKey, Class<E1> exceptionClass1,
-        Class<E2> exceptionClass2, Class<E3> exceptionClass3, Class<E4> exceptionClass4)
-            throws E1, E2, E3, E4;
+        SkyValue getValueOrThrow(
+            SkyKey depKey,
+            Class<E1> exceptionClass1,
+            Class<E2> exceptionClass2,
+            Class<E3> exceptionClass3,
+            Class<E4> exceptionClass4)
+            throws E1, E2, E3, E4, InterruptedException;
+
     @Nullable
-    <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception,
-     E5 extends Exception>
-        SkyValue getValueOrThrow(SkyKey depKey, Class<E1> exceptionClass1,
-        Class<E2> exceptionClass2, Class<E3> exceptionClass3, Class<E4> exceptionClass4,
-        Class<E5> exceptionClass5) throws E1, E2, E3, E4, E5;
+    <
+            E1 extends Exception,
+            E2 extends Exception,
+            E3 extends Exception,
+            E4 extends Exception,
+            E5 extends Exception>
+        SkyValue getValueOrThrow(
+            SkyKey depKey,
+            Class<E1> exceptionClass1,
+            Class<E2> exceptionClass2,
+            Class<E3> exceptionClass3,
+            Class<E4> exceptionClass4,
+            Class<E5> exceptionClass5)
+            throws E1, E2, E3, E4, E5, InterruptedException;
 
     /**
      * Requests {@code depKeys} "in parallel", independent of each others' values. These keys may be
@@ -131,27 +156,27 @@
      * <p>This means that on subsequent evaluations, when checking to see if dependencies require
      * re-evaluation, all the values in this group may be simultaneously checked. A SkyFunction
      * should request a dependency group if checking the deps serially on a subsequent evaluation
-     * would take too long, and if the {@link #compute} method would request all deps anyway as
-     * long as no earlier deps had changed. SkyFunction.Environment implementations may also
-     * choose to request these deps in parallel on the first evaluation, potentially speeding it up.
+     * would take too long, and if the {@link #compute} method would request all deps anyway as long
+     * as no earlier deps had changed. SkyFunction.Environment implementations may also choose to
+     * request these deps in parallel on the first evaluation, potentially speeding it up.
      *
-     * <p>While re-evaluating every value in the group may take longer than re-evaluating just
-     * the first one and finding that it has changed, no extra work is done: the contract of the
+     * <p>While re-evaluating every value in the group may take longer than re-evaluating just the
+     * first one and finding that it has changed, no extra work is done: the contract of the
      * dependency group means that the {@link #compute} method, when called to re-evaluate this
      * value, will request all values in the group again anyway, so they would have to have been
      * built in any case.
      *
      * <p>Example of when to use getValues: A ListProcessor value is built with key inputListRef.
-     * The {@link #compute} method first calls getValue(InputList.key(inputListRef)), and
-     * retrieves inputList. It then iterates through inputList, calling getValue on each input.
-     * Finally, it processes the whole list and returns. Say inputList is (a, b, c). Since the
-     * {@link #compute} method will unconditionally call getValue(a), getValue(b), and getValue
-     * (c), the {@link #compute} method can instead just call getValues({a, b, c}). If the value
-     * is later dirtied the evaluator will evaluate a, b, and c in parallel (assuming the inputList
-     * value was unchanged), and re-evaluate the ListProcessor value only if at least one of them
-     * was changed. On the other hand, if the InputList changes to be (a, b, d), then the
-     * evaluator will see that the first dep has changed, and call the {@link #compute} method to
-     * re-evaluate from scratch, without considering the dep group of {a, b, c}.
+     * The {@link #compute} method first calls getValue(InputList.key(inputListRef)), and retrieves
+     * inputList. It then iterates through inputList, calling getValue on each input. Finally, it
+     * processes the whole list and returns. Say inputList is (a, b, c). Since the {@link #compute}
+     * method will unconditionally call getValue(a), getValue(b), and getValue (c), the {@link
+     * #compute} method can instead just call getValues({a, b, c}). If the value is later dirtied
+     * the evaluator will evaluate a, b, and c in parallel (assuming the inputList value was
+     * unchanged), and re-evaluate the ListProcessor value only if at least one of them was changed.
+     * On the other hand, if the InputList changes to be (a, b, d), then the evaluator will see that
+     * the first dep has changed, and call the {@link #compute} method to re-evaluate from scratch,
+     * without considering the dep group of {a, b, c}.
      *
      * <p>Example of when not to use getValues: A BestMatch value is built with key
      * &lt;potentialMatchesRef, matchCriterion&gt;. The {@link #compute} method first calls
@@ -165,43 +190,64 @@
      * is {@code true}, and, {@code m.get(k) != null} iff the dependency was already evaluated and
      * was not in error.
      */
-    Map<SkyKey, SkyValue> getValues(Iterable<SkyKey> depKeys);
+    Map<SkyKey, SkyValue> getValues(Iterable<SkyKey> depKeys) throws InterruptedException;
 
     /**
-     * Similar to {@link #getValues} but allows the caller to specify a set of types that are
-     * proper subtypes of Exception (see {@link SkyFunctionException} for more details) to find
-     * out whether any of the dependencies' evaluations resulted in exceptions of those types.
-     * The returned objects may throw when attempting to retrieve their value.
+     * Similar to {@link #getValues} but allows the caller to specify a set of types that are proper
+     * subtypes of Exception (see {@link SkyFunctionException} for more details) to find out whether
+     * any of the dependencies' evaluations resulted in exceptions of those types. The returned
+     * objects may throw when attempting to retrieve their value.
      *
-     * <p>Callers should prioritize their responsibility to detect and handle errors in the
-     * returned map over their responsibility to return {@code null} if values are missing. This
-     * is because in nokeep_going evaluations, an error from a low level dependency is given a
-     * chance to be enriched by its reverse-dependencies, if possible.
+     * <p>Callers should prioritize their responsibility to detect and handle errors in the returned
+     * map over their responsibility to return {@code null} if values are missing. This is because
+     * in nokeep_going evaluations, an error from a low level dependency is given a chance to be
+     * enriched by its reverse-dependencies, if possible.
      *
-     * <p>Returns a map, {@code m}. For all {@code k} in {@code depKeys}, {@code m.get(k) !=
-     * null}. For all {@code v} such that there is some {@code k} such that {@code m.get(k) ==
-     * v}, the following is true: {@code v.get() != null} iff the dependency {@code k} was
-     * already evaluated and was not in error. {@code v.get()} throws {@code E} iff the
-     * dependency {@code k} was already evaluated with an error in the specified set of {@link
-     * Exception} types.
+     * <p>Returns a map, {@code m}. For all {@code k} in {@code depKeys}, {@code m.get(k) != null}.
+     * For all {@code v} such that there is some {@code k} such that {@code m.get(k) == v}, the
+     * following is true: {@code v.get() != null} iff the dependency {@code k} was already evaluated
+     * and was not in error. {@code v.get()} throws {@code E} iff the dependency {@code k} was
+     * already evaluated with an error in the specified set of {@link Exception} types.
      */
     <E extends Exception> Map<SkyKey, ValueOrException<E>> getValuesOrThrow(
-        Iterable<SkyKey> depKeys, Class<E> exceptionClass);
-    <E1 extends Exception, E2 extends Exception> Map<SkyKey, ValueOrException2<E1, E2>>
-    getValuesOrThrow(Iterable<SkyKey> depKeys, Class<E1> exceptionClass1,
-        Class<E2> exceptionClass2);
+        Iterable<SkyKey> depKeys, Class<E> exceptionClass) throws InterruptedException;
+
+    <E1 extends Exception, E2 extends Exception>
+        Map<SkyKey, ValueOrException2<E1, E2>> getValuesOrThrow(
+            Iterable<SkyKey> depKeys, Class<E1> exceptionClass1, Class<E2> exceptionClass2)
+            throws InterruptedException;
+
     <E1 extends Exception, E2 extends Exception, E3 extends Exception>
-    Map<SkyKey, ValueOrException3<E1, E2, E3>> getValuesOrThrow(Iterable<SkyKey> depKeys,
-        Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3);
+        Map<SkyKey, ValueOrException3<E1, E2, E3>> getValuesOrThrow(
+            Iterable<SkyKey> depKeys,
+            Class<E1> exceptionClass1,
+            Class<E2> exceptionClass2,
+            Class<E3> exceptionClass3)
+            throws InterruptedException;
+
     <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception>
-    Map<SkyKey, ValueOrException4<E1, E2, E3, E4>> getValuesOrThrow(Iterable<SkyKey> depKeys,
-        Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3,
-        Class<E4> exceptionClass4);
-    <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception,
-     E5 extends Exception>
-    Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValuesOrThrow(Iterable<SkyKey> depKeys,
-        Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3,
-        Class<E4> exceptionClass4, Class<E5> exceptionClass5);
+        Map<SkyKey, ValueOrException4<E1, E2, E3, E4>> getValuesOrThrow(
+            Iterable<SkyKey> depKeys,
+            Class<E1> exceptionClass1,
+            Class<E2> exceptionClass2,
+            Class<E3> exceptionClass3,
+            Class<E4> exceptionClass4)
+            throws InterruptedException;
+
+    <
+            E1 extends Exception,
+            E2 extends Exception,
+            E3 extends Exception,
+            E4 extends Exception,
+            E5 extends Exception>
+        Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValuesOrThrow(
+            Iterable<SkyKey> depKeys,
+            Class<E1> exceptionClass1,
+            Class<E2> exceptionClass2,
+            Class<E3> exceptionClass3,
+            Class<E4> exceptionClass4,
+            Class<E5> exceptionClass5)
+            throws InterruptedException;
 
     /**
      * Returns whether there was a previous getValue[s][OrThrow] that indicated a missing
diff --git a/src/main/java/com/google/devtools/build/skyframe/ThinNodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/ThinNodeEntry.java
index f81355c..1ef077c 100644
--- a/src/main/java/com/google/devtools/build/skyframe/ThinNodeEntry.java
+++ b/src/main/java/com/google/devtools/build/skyframe/ThinNodeEntry.java
@@ -15,7 +15,6 @@
 
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import javax.annotation.Nullable;
 
 /**
@@ -47,23 +46,23 @@
 
   /**
    * Marks this node dirty, or changed if {@code isChanged} is true. The node is put in the
-   * just-created state. It will be re-evaluated if necessary during the evaluation phase,
-   * but if it has not changed, it will not force a re-evaluation of its parents.
+   * just-created state. It will be re-evaluated if necessary during the evaluation phase, but if it
+   * has not changed, it will not force a re-evaluation of its parents.
    *
-   * <p>{@code markDirty(b)} must not be called on an undone node if {@code isChanged() == b}.
-   * It is the caller's responsibility to ensure that this does not happen.  Calling
-   * {@code markDirty(false)} when {@code isChanged() == true} has no effect. The idea here is that
-   * the caller will only ever want to call {@code markDirty()} a second time if a transition from a
+   * <p>{@code markDirty(b)} must not be called on an undone node if {@code isChanged() == b}. It is
+   * the caller's responsibility to ensure that this does not happen. Calling {@code
+   * markDirty(false)} when {@code isChanged() == true} has no effect. The idea here is that the
+   * caller will only ever want to call {@code markDirty()} a second time if a transition from a
    * dirty-unchanged state to a dirty-changed state is required.
    *
-   * @return A {@link ThinNodeEntry.MarkedDirtyResult} if the node was previously clean, and
-   * {@code null} if it was already dirty. If it was already dirty, the caller should abort its
-   * handling of this node, since another thread is already dealing with it. Note the warning on
-   * {@link ThinNodeEntry.MarkedDirtyResult} regarding the collection it provides.
+   * @return A {@link ThinNodeEntry.MarkedDirtyResult} if the node was previously clean, and {@code
+   *     null} if it was already dirty. If it was already dirty, the caller should abort its
+   *     handling of this node, since another thread is already dealing with it. Note the warning on
+   *     {@link ThinNodeEntry.MarkedDirtyResult} regarding the collection it provides.
    */
   @Nullable
   @ThreadSafe
-  MarkedDirtyResult markDirty(boolean isChanged);
+  MarkedDirtyResult markDirty(boolean isChanged) throws InterruptedException;
 
   /**
    * Returned by {@link #markDirty} if that call changed the node from clean to dirty. Contains an
diff --git a/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java b/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java
index 7c7a7e8..9f71f1f 100644
--- a/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java
+++ b/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java
@@ -15,15 +15,17 @@
 
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.events.EventHandler;
-
 import java.util.Collection;
 import java.util.Map;
-
 import javax.annotation.Nullable;
 
 /**
  * Read-only graph that exposes the dependents, dependencies (reverse dependents), and value and
  * exception (if any) of a given node.
+ *
+ * <p>Certain graph implementations can throw {@link InterruptedException} when trying to retrieve
+ * node entries. Such exceptions should not be caught locally -- they should be allowed to propagate
+ * up.
  */
 @ThreadSafe
 public interface WalkableGraph {
@@ -33,21 +35,21 @@
    * given node does not exist, this method should be called before any others, since the others
    * throw a {@link RuntimeException} on failure to access a node.
    */
-  boolean exists(SkyKey key);
+  boolean exists(SkyKey key) throws InterruptedException;
 
   /**
    * Returns the value of the given key, or {@code null} if it has no value due to an error during
    * its computation. A node with this key must exist in the graph.
    */
   @Nullable
-  SkyValue getValue(SkyKey key);
+  SkyValue getValue(SkyKey key) throws InterruptedException;
 
   /**
    * Returns a map giving the values of the given keys for done keys that were successfully
-   * computed. Or in other words, it filters out non-existent nodes, pending nodes and nodes
-   * that produced an exception.
+   * computed. Or in other words, it filters out non-existent nodes, pending nodes and nodes that
+   * produced an exception.
    */
-  Map<SkyKey, SkyValue> getSuccessfulValues(Iterable<SkyKey> keys);
+  Map<SkyKey, SkyValue> getSuccessfulValues(Iterable<SkyKey> keys) throws InterruptedException;
 
   /**
    * Returns a map giving exceptions associated to the given keys for done keys. Keys not present in
@@ -56,26 +58,27 @@
    * for {@code key} if and only if the node for {@code key} did <i>not</i> evaluate successfully
    * without error.
    */
-  Map<SkyKey, Exception> getMissingAndExceptions(Iterable<SkyKey> keys);
+  Map<SkyKey, Exception> getMissingAndExceptions(Iterable<SkyKey> keys) throws InterruptedException;
 
   /**
    * Returns the exception thrown when computing the node with the given key, if any. If the node
    * was computed successfully, returns null. A node with this key must exist and be done in the
    * graph.
    */
-  @Nullable Exception getException(SkyKey key);
+  @Nullable
+  Exception getException(SkyKey key) throws InterruptedException;
 
   /**
    * Returns a map giving the direct dependencies of the nodes with the given keys. A node for each
    * given key must exist and be done in the graph.
    */
-  Map<SkyKey, Iterable<SkyKey>> getDirectDeps(Iterable<SkyKey> keys);
+  Map<SkyKey, Iterable<SkyKey>> getDirectDeps(Iterable<SkyKey> keys) throws InterruptedException;
 
   /**
    * Returns a map giving the reverse dependencies of the nodes with the given keys. A node for each
    * given key must exist and be done in the graph.
    */
-  Map<SkyKey, Iterable<SkyKey>> getReverseDeps(Iterable<SkyKey> keys);
+  Map<SkyKey, Iterable<SkyKey>> getReverseDeps(Iterable<SkyKey> keys) throws InterruptedException;
 
   /** Provides a WalkableGraph on demand after preparing it. */
   interface WalkableGraphFactory {