Skip to content

Commit be4cbc7

Browse files
committed
Revert "Move use of legacy sandbox -> local fallback to only be used after all strategies have been tried, and improve messages around it."
This reverts commit b2231c5.
1 parent e6809c9 commit be4cbc7

File tree

7 files changed

+95
-162
lines changed

7 files changed

+95
-162
lines changed

src/main/java/com/google/devtools/build/lib/actions/SpawnStrategy.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,9 @@ default SpawnContinuation beginExecution(
5050
}
5151
}
5252

53-
/**
54-
* Returns whether this SpawnActionContext supports executing the given Spawn. This does not allow
55-
* using the legacy fallback to local execution controlled by the {@code
56-
* --incompatible_legacy_local_fallback} flag.
57-
*/
53+
/** Returns whether this SpawnActionContext supports executing the given Spawn. */
5854
boolean canExec(Spawn spawn, ActionContext.ActionContextRegistry actionContextRegistry);
5955

60-
/**
61-
* Returns true if this SpawnActionContext supports executing the given Spawn through a legacy
62-
* fallback system. This will only be used if no SpawnActionContexts were able to execute it by
63-
* normal means.
64-
*/
65-
default boolean canExecWithLegacyFallback(
66-
Spawn spawn, ActionContext.ActionContextRegistry actionContextRegistry) {
67-
return false;
68-
}
69-
7056
/**
7157
* Performs any actions conditional on this strategy not only being registered but triggered as
7258
* used because its identifier was requested and it was not overridden.

src/main/java/com/google/devtools/build/lib/dynamic/DynamicSpawnStrategy.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,7 @@ public boolean canExec(Spawn spawn, ActionContext.ActionContextRegistry actionCo
433433
for (SandboxedSpawnStrategy strategy :
434434
dynamicStrategyRegistry.getDynamicSpawnActionContexts(
435435
spawn, DynamicStrategyRegistry.DynamicMode.LOCAL)) {
436-
if (strategy.canExec(spawn, actionContextRegistry)
437-
|| strategy.canExecWithLegacyFallback(spawn, actionContextRegistry)) {
436+
if (strategy.canExec(spawn, actionContextRegistry)) {
438437
return true;
439438
}
440439
}
@@ -475,8 +474,7 @@ private static ImmutableList<SpawnResult> runLocally(
475474
for (SandboxedSpawnStrategy strategy :
476475
dynamicStrategyRegistry.getDynamicSpawnActionContexts(
477476
spawn, DynamicStrategyRegistry.DynamicMode.LOCAL)) {
478-
if (strategy.canExec(spawn, actionExecutionContext)
479-
|| strategy.canExecWithLegacyFallback(spawn, actionExecutionContext)) {
477+
if (strategy.canExec(spawn, actionExecutionContext)) {
480478
return strategy.exec(spawn, actionExecutionContext, stopConcurrentSpawns);
481479
}
482480
}

src/main/java/com/google/devtools/build/lib/exec/AbstractSpawnStrategy.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,6 @@ public boolean canExec(Spawn spawn, ActionContext.ActionContextRegistry actionCo
9494
return spawnRunner.canExec(spawn);
9595
}
9696

97-
@Override
98-
public boolean canExecWithLegacyFallback(
99-
Spawn spawn, ActionContext.ActionContextRegistry actionContextRegistry) {
100-
return spawnRunner.canExecWithLegacyFallback(spawn);
101-
}
102-
10397
@Override
10498
public ImmutableList<SpawnResult> exec(Spawn spawn, ActionExecutionContext actionExecutionContext)
10599
throws ExecException, InterruptedException {

src/main/java/com/google/devtools/build/lib/exec/SpawnRunner.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,6 @@ SpawnResult exec(Spawn spawn, SpawnExecutionContext context)
255255
/** Returns whether this SpawnRunner supports executing the given Spawn. */
256256
boolean canExec(Spawn spawn);
257257

258-
/** Returns whether this SpawnRunner supports executing the given Spawn using legacy fallbacks. */
259-
default boolean canExecWithLegacyFallback(Spawn spawn) {
260-
return false;
261-
}
262-
263258
/** Returns whether this SpawnRunner handles caching of actions internally. */
264259
boolean handlesCaching();
265260

src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyResolver.java

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,37 +88,26 @@ public List<? extends SpawnStrategy> resolve(
8888
.getContext(SpawnStrategyRegistry.class)
8989
.getStrategies(spawn, actionExecutionContext.getEventHandler());
9090

91-
List<? extends SpawnStrategy> execableStrategies =
91+
strategies =
9292
strategies.stream()
9393
.filter(spawnActionContext -> spawnActionContext.canExec(spawn, actionExecutionContext))
9494
.collect(Collectors.toList());
9595

96-
if (execableStrategies.isEmpty()) {
97-
// Legacy implicit fallbacks should be a last-ditch option after all other strategies are
98-
// found non-executable.
99-
List<? extends SpawnStrategy> fallbackStrategies =
100-
strategies.stream()
101-
.filter(
102-
spawnActionContext ->
103-
spawnActionContext.canExecWithLegacyFallback(spawn, actionExecutionContext))
104-
.collect(Collectors.toList());
105-
106-
if (fallbackStrategies.isEmpty()) {
107-
String message =
108-
String.format(
109-
"No usable spawn strategy found for spawn with mnemonic %s. Your --spawn_strategy,"
110-
+ " --genrule_strategy and/or --strategy flags are probably too strict. Visit"
111-
+ " https://github.com/bazelbuild/bazel/issues/7480 for migration advice",
112-
spawn.getMnemonic());
113-
throw new UserExecException(
114-
FailureDetail.newBuilder()
115-
.setMessage(message)
116-
.setSpawn(FailureDetails.Spawn.newBuilder().setCode(Code.NO_USABLE_STRATEGY_FOUND))
117-
.build());
118-
}
119-
return fallbackStrategies;
96+
if (strategies.isEmpty()) {
97+
String message =
98+
String.format(
99+
"No usable spawn strategy found for spawn with mnemonic %s. Your"
100+
+ " --spawn_strategy, --genrule_strategy and/or --strategy flags are probably too"
101+
+ " strict. Visit https://github.com/bazelbuild/bazel/issues/7480 for"
102+
+ " migration advice",
103+
spawn.getMnemonic());
104+
throw new UserExecException(
105+
FailureDetail.newBuilder()
106+
.setMessage(message)
107+
.setSpawn(FailureDetails.Spawn.newBuilder().setCode(Code.NO_USABLE_STRATEGY_FOUND))
108+
.build());
120109
}
121110

122-
return execableStrategies;
111+
return strategies;
123112
}
124113
}

src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java

Lines changed: 14 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -429,11 +429,12 @@ private static Path getPathToDockerClient(CommandEnvironment cmdEnv) {
429429
private static SpawnRunner withFallback(
430430
CommandEnvironment env, AbstractSandboxSpawnRunner sandboxSpawnRunner) {
431431
SandboxOptions sandboxOptions = env.getOptions().getOptions(SandboxOptions.class);
432-
return new SandboxFallbackSpawnRunner(
433-
sandboxSpawnRunner,
434-
createFallbackRunner(env),
435-
env.getReporter(),
436-
sandboxOptions != null && sandboxOptions.legacyLocalFallback);
432+
if (sandboxOptions != null && sandboxOptions.legacyLocalFallback) {
433+
return new SandboxFallbackSpawnRunner(
434+
sandboxSpawnRunner, createFallbackRunner(env), env.getReporter());
435+
} else {
436+
return sandboxSpawnRunner;
437+
}
437438
}
438439

439440
private static SpawnRunner createFallbackRunner(CommandEnvironment env) {
@@ -450,29 +451,19 @@ private static SpawnRunner createFallbackRunner(CommandEnvironment env) {
450451
RunfilesTreeUpdater.INSTANCE);
451452
}
452453

453-
/**
454-
* A SpawnRunner that does sandboxing if possible, but might fall back to local execution if
455-
* ----incompatible_legacy_local_fallback is true and no other strategy has been usable. This is a
456-
* legacy functionality from before the strategies system was added, and can deceive the user into
457-
* thinking a build is hermetic when it isn't really. TODO(b/178356138): Flip flag to default to
458-
* false and then later remove this code entirely.
459-
*/
460454
private static final class SandboxFallbackSpawnRunner implements SpawnRunner {
461455
private final SpawnRunner sandboxSpawnRunner;
462456
private final SpawnRunner fallbackSpawnRunner;
463457
private final ExtendedEventHandler reporter;
464458
private static final AtomicBoolean warningEmitted = new AtomicBoolean();
465-
private final boolean fallbackAllowed;
466459

467460
SandboxFallbackSpawnRunner(
468461
SpawnRunner sandboxSpawnRunner,
469462
SpawnRunner fallbackSpawnRunner,
470-
ExtendedEventHandler reporter,
471-
boolean fallbackAllowed) {
463+
ExtendedEventHandler reporter) {
472464
this.sandboxSpawnRunner = sandboxSpawnRunner;
473465
this.fallbackSpawnRunner = fallbackSpawnRunner;
474466
this.reporter = reporter;
475-
this.fallbackAllowed = fallbackAllowed;
476467
}
477468

478469
@Override
@@ -488,6 +479,12 @@ public SpawnResult exec(Spawn spawn, SpawnExecutionContext context)
488479
if (sandboxSpawnRunner.canExec(spawn)) {
489480
spawnResult = sandboxSpawnRunner.exec(spawn, context);
490481
} else {
482+
if (warningEmitted.compareAndSet(false, true)) {
483+
reporter.handle(
484+
Event.warn(
485+
"Use of implicit local fallback will go away soon, please"
486+
+ " set a fallback strategy instead. See --legacy_local_fallback option."));
487+
}
491488
spawnResult = fallbackSpawnRunner.exec(spawn, context);
492489
}
493490
reporter.post(new SpawnExecutedEvent(spawn, spawnResult, spawnExecutionStartInstant));
@@ -496,38 +493,7 @@ public SpawnResult exec(Spawn spawn, SpawnExecutionContext context)
496493

497494
@Override
498495
public boolean canExec(Spawn spawn) {
499-
return sandboxSpawnRunner.canExec(spawn);
500-
}
501-
502-
@Override
503-
public boolean canExecWithLegacyFallback(Spawn spawn) {
504-
boolean canExec = !sandboxSpawnRunner.canExec(spawn) && fallbackSpawnRunner.canExec(spawn);
505-
if (canExec) {
506-
// We give a single warning to use strategies instead, whether or not we allow the fallback
507-
// to happen. This allows people to switch early, but also explains why the build fails
508-
// once we flip the flag. Unfortunately, we can't easily tell if the flag was explicitly
509-
// set, if we could we should omit the warnings in that case.
510-
if (warningEmitted.compareAndSet(false, true)) {
511-
if (fallbackAllowed) {
512-
reporter.handle(
513-
Event.warn(
514-
String.format(
515-
"%s uses implicit fallback from sandbox to local, which is deprecated"
516-
+ " because it is not hermetic. Prefer setting an explicit list of"
517-
+ " strategies.",
518-
spawn.getMnemonic())));
519-
} else {
520-
reporter.handle(
521-
Event.warn(
522-
String.format(
523-
"Implicit fallback from sandbox to local is deprecated. Prefer setting an"
524-
+ " explicit list of strategies for %s, or for now pass"
525-
+ " --incompatible_legacy_local_fallback.",
526-
spawn.getMnemonic())));
527-
}
528-
}
529-
}
530-
return canExec && fallbackAllowed;
496+
return sandboxSpawnRunner.canExec(spawn) || fallbackSpawnRunner.canExec(spawn);
531497
}
532498

533499
@Override

src/main/java/com/google/devtools/build/lib/sandbox/SandboxOptions.java

Lines changed: 63 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,12 @@ public String getTypeDescription() {
8080
}
8181

8282
@Option(
83-
name = "ignore_unsupported_sandboxing",
84-
defaultValue = "false",
85-
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
86-
effectTags = {OptionEffectTag.UNKNOWN},
87-
help = "Do not print a warning when sandboxed execution is not supported on this system.")
83+
name = "ignore_unsupported_sandboxing",
84+
defaultValue = "false",
85+
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
86+
effectTags = {OptionEffectTag.UNKNOWN},
87+
help = "Do not print a warning when sandboxed execution is not supported on this system."
88+
)
8889
public boolean ignoreUnsupportedSandboxing;
8990

9091
@Option(
@@ -114,19 +115,21 @@ public String getTypeDescription() {
114115
public String sandboxBase;
115116

116117
@Option(
117-
name = "sandbox_fake_hostname",
118-
defaultValue = "false",
119-
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
120-
effectTags = {OptionEffectTag.UNKNOWN},
121-
help = "Change the current hostname to 'localhost' for sandboxed actions.")
118+
name = "sandbox_fake_hostname",
119+
defaultValue = "false",
120+
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
121+
effectTags = {OptionEffectTag.UNKNOWN},
122+
help = "Change the current hostname to 'localhost' for sandboxed actions."
123+
)
122124
public boolean sandboxFakeHostname;
123125

124126
@Option(
125-
name = "sandbox_fake_username",
126-
defaultValue = "false",
127-
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
128-
effectTags = {OptionEffectTag.UNKNOWN},
129-
help = "Change the current username to 'nobody' for sandboxed actions.")
127+
name = "sandbox_fake_username",
128+
defaultValue = "false",
129+
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
130+
effectTags = {OptionEffectTag.UNKNOWN},
131+
help = "Change the current username to 'nobody' for sandboxed actions."
132+
)
130133
public boolean sandboxFakeUsername;
131134

132135
@Option(
@@ -184,13 +187,14 @@ public String getTypeDescription() {
184187
public TriState useSandboxfs;
185188

186189
@Option(
187-
name = "experimental_sandboxfs_path",
188-
defaultValue = "sandboxfs",
189-
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
190-
effectTags = {OptionEffectTag.UNKNOWN},
191-
help =
192-
"Path to the sandboxfs binary to use when --experimental_use_sandboxfs is true. If a "
193-
+ "bare name, use the first binary of that name found in the PATH.")
190+
name = "experimental_sandboxfs_path",
191+
defaultValue = "sandboxfs",
192+
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
193+
effectTags = {OptionEffectTag.UNKNOWN},
194+
help =
195+
"Path to the sandboxfs binary to use when --experimental_use_sandboxfs is true. If a "
196+
+ "bare name, use the first binary of that name found in the PATH."
197+
)
194198
public String sandboxfsPath;
195199

196200
@Option(
@@ -243,48 +247,50 @@ public ImmutableSet<Path> getInaccessiblePaths(FileSystem fs) {
243247
}
244248

245249
@Option(
246-
name = "experimental_collect_local_sandbox_action_metrics",
247-
defaultValue = "false",
248-
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
249-
effectTags = {OptionEffectTag.EXECUTION},
250-
help =
251-
"When enabled, execution statistics (such as user and system time) are recorded for "
252-
+ "locally executed actions which use sandboxing")
250+
name = "experimental_collect_local_sandbox_action_metrics",
251+
defaultValue = "false",
252+
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
253+
effectTags = {OptionEffectTag.EXECUTION},
254+
help =
255+
"When enabled, execution statistics (such as user and system time) are recorded for "
256+
+ "locally executed actions which use sandboxing"
257+
)
253258
public boolean collectLocalSandboxExecutionStatistics;
254259

255260
@Option(
256-
name = "experimental_enable_docker_sandbox",
257-
defaultValue = "false",
258-
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
259-
effectTags = {OptionEffectTag.EXECUTION},
260-
help =
261-
"Enable Docker-based sandboxing. This option has no effect if Docker is not installed.")
261+
name = "experimental_enable_docker_sandbox",
262+
defaultValue = "false",
263+
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
264+
effectTags = {OptionEffectTag.EXECUTION},
265+
help = "Enable Docker-based sandboxing. This option has no effect if Docker is not installed.")
262266
public boolean enableDockerSandbox;
263267

264268
@Option(
265-
name = "experimental_docker_image",
266-
defaultValue = "",
267-
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
268-
effectTags = {OptionEffectTag.EXECUTION},
269-
help =
270-
"Specify a Docker image name (e.g. \"ubuntu:latest\") that should be used to execute a"
271-
+ " sandboxed action when using the docker strategy and the action itself doesn't"
272-
+ " already have a container-image attribute in its remote_execution_properties in"
273-
+ " the platform description. The value of this flag is passed verbatim to 'docker"
274-
+ " run', so it supports the same syntax and mechanisms as Docker itself.")
269+
name = "experimental_docker_image",
270+
defaultValue = "",
271+
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
272+
effectTags = {OptionEffectTag.EXECUTION},
273+
help =
274+
"Specify a Docker image name (e.g. \"ubuntu:latest\") that should be used to execute "
275+
+ "a sandboxed action when using the docker strategy and the action itself doesn't "
276+
+ "already have a container-image attribute in its remote_execution_properties in the "
277+
+ "platform description. The value of this flag is passed verbatim to 'docker run', so "
278+
+ "it supports the same syntax and mechanisms as Docker itself."
279+
)
275280
public String dockerImage;
276281

277282
@Option(
278-
name = "experimental_docker_use_customized_images",
279-
defaultValue = "true",
280-
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
281-
effectTags = {OptionEffectTag.EXECUTION},
282-
help =
283-
"If enabled, injects the uid and gid of the current user into the Docker image before"
284-
+ " using it. This is required if your build / tests depend on the user having a name"
285-
+ " and home directory inside the container. This is on by default, but you can"
286-
+ " disable it in case the automatic image customization feature doesn't work in your"
287-
+ " case or you know that you don't need it.")
283+
name = "experimental_docker_use_customized_images",
284+
defaultValue = "true",
285+
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
286+
effectTags = {OptionEffectTag.EXECUTION},
287+
help =
288+
"If enabled, injects the uid and gid of the current user into the Docker image before "
289+
+ "using it. This is required if your build / tests depend on the user having a name "
290+
+ "and home directory inside the container. This is on by default, but you can disable "
291+
+ "it in case the automatic image customization feature doesn't work in your case or "
292+
+ "you know that you don't need it."
293+
)
288294
public boolean dockerUseCustomizedImages;
289295

290296
@Option(
@@ -353,9 +359,8 @@ public ImmutableSet<Path> getInaccessiblePaths(FileSystem fs) {
353359
},
354360
help =
355361
"If set to true, enables the legacy implicit fallback from sandboxed to local strategy."
356-
+ " This flag will eventually default to false and then become a no-op. Use"
357-
+ " --strategy, --spawn_strategy, or --dynamic_local_strategy to configure fallbacks"
358-
+ " instead.")
362+
+ " This flag will eventually default to false and then become a no-op. You should"
363+
+ " use --strategy or --spawn_strategy to configure fallbacks instead.")
359364
public boolean legacyLocalFallback;
360365

361366
/** Converter for the number of threads used for asynchronous tree deletion. */

0 commit comments

Comments
 (0)