Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reject symlink outputs from cachable actions #4840

Closed
benjaminp opened this issue Mar 14, 2018 · 16 comments
Closed

reject symlink outputs from cachable actions #4840

benjaminp opened this issue Mar 14, 2018 · 16 comments
Assignees

Comments

@benjaminp
Copy link
Collaborator

The remote caching protocol doesn't know about symlinks, and the remote spawn strategy currently converts all symlink into regular files when uploading to the cache. This behavior is insidious because local execution preserves symlinks. So, local and remote execution may yield different results if symlinks are involved:

$ mkdir /tmp/my-cache
$ cat BUILD
genrule(
    name = 'emit-symlink',
    outs = [':a', ':b'],
    cmd = '''
touch $(location :a)
ln -s a $(location :b)
''',
)
$ bazel build --experimental_local_disk_cache --experimental_local_disk_cache_path /tmp/my-cache :emit-symlink
$ ls -lh bazel-genfiles/
total 0
-r-xr-xr-x 1 benjamin benjamin 0 Mar 13 02:35 a
lrwxrwxrwx 1 benjamin benjamin 1 Mar 13 02:35 b -> a
$ bazel clean --expunge
$ bazel build --experimental_local_disk_cache --experimental_local_disk_cache_path /tmp/my-cache :emit-symlink
$ ls -lh bazel-genfiles/
total 0
-r-xr-xr-x 1 benjamin benjamin 0 Mar 14 02:36 a
-r-xr-xr-x 1 benjamin benjamin 0 Mar 14 02:36 b

Handling symlinks in remote caching seems tricky. (What if the link target is absolute?) Therefore, I propose that trying to upload a symlink output to the cache should be an error.

@nicolov
Copy link
Contributor

nicolov commented Mar 15, 2018

Agree, this impacted us too until I sprinkled some "no-cache" tags.

@buchgr buchgr self-assigned this Mar 15, 2018
@buchgr
Copy link
Contributor

buchgr commented Mar 15, 2018

That sounds good to me. We should probably output a decent error message indicating that this action should be tagged "no-cache". Do you want to work on this @benjaminp?

@buchgr
Copy link
Contributor

buchgr commented Mar 15, 2018

@nicolov for which rules did you encounter this behavior?

@nicolov
Copy link
Contributor

nicolov commented Mar 15, 2018 via email

@benjaminp
Copy link
Collaborator Author

Sure, I can work on a patch.

@buchgr
Copy link
Contributor

buchgr commented Mar 15, 2018

Thank you @benjaminp

@buchgr
Copy link
Contributor

buchgr commented Mar 16, 2018

Hey @benjaminp,

I have discussed this issue with a few people on the Bazel team:

  • We must not cache actions that output symlinks to absolute paths.
  • We may cache relative symlinks to inputs or outputs of that particular action, but that's an optimization that doesn't need to be included in your patch (and might make things just more complicated).
  • Downstream actions (actions having a symlink output as an input) should resolve the symlink and use the content hash in their action key computation.
  • There are mixed opinions about whether trying to upload a symlink should be an error or a warning. I personally lean more towards printing a warning and not caching the action, as it seems more user friendly. What do you think?

@benjaminp
Copy link
Collaborator Author

I have discussed this issue with a few people on the Bazel team:

Thanks for the guidance.

There are mixed opinions about whether trying to upload a symlink should be an error or a warning. I personally lean more towards printing a warning and not caching the action, as it seems more user friendly. What do you think?

I think it should be an error. Warnings are fine for informing users about transient conditions like the remote cache being down. An action producing symlinks is similar to an action not producing promised artifacts. It's an unambiguous deterministic function of the (gen)rule implementation.

@buchgr
Copy link
Contributor

buchgr commented Mar 17, 2018

Sounds reasonable :). Thanks.

benjaminp added a commit to benjaminp/bazel that referenced this issue Mar 22, 2018
… to a remote cache.

The remote cache protocol only knows about regular files and
directories. Currently, during action output upload, symlinks are
resolved into regular files. This means cached "executions" of an
action may have different output file types than the original
execution, which can be a footgun. This CL bans symlinks from cachable
spawn outputs and fixes bazelbuild#4840.

The interface of SpawnCache.CacheHandle.store is refactored:
1. The outputs parameter is removed, since that can be retrieved from the underlying Spawn.
2. It can now throw ExecException in order to fail actions.

Change-Id: I0d1d94d48779b970bb5d0840c66a14c189ab0091
benjaminp added a commit to benjaminp/bazel that referenced this issue Mar 22, 2018
… to a remote cache.

The remote cache protocol only knows about regular files and
directories. Currently, during action output upload, symlinks are
resolved into regular files. This means cached "executions" of an
action may have different output file types than the original
execution, which can be a footgun. This CL bans symlinks from cachable
spawn outputs and fixes bazelbuild#4840.

The interface of SpawnCache.CacheHandle.store is refactored:
1. The outputs parameter is removed, since that can be retrieved from the underlying Spawn.
2. It can now throw ExecException in order to fail actions.

Change-Id: I0d1d94d48779b970bb5d0840c66a14c189ab0091
benjaminp added a commit to benjaminp/bazel that referenced this issue Mar 23, 2018
… to a remote cache.

The remote cache protocol only knows about regular files and
directories. Currently, during action output upload, symlinks are
resolved into regular files. This means cached "executions" of an
action may have different output file types than the original
execution, which can be a footgun. This CL bans symlinks from cachable
spawn outputs and fixes bazelbuild#4840.

The interface of SpawnCache.CacheHandle.store is refactored:
1. The outputs parameter is removed, since that can be retrieved from the underlying Spawn.
2. It can now throw ExecException in order to fail actions.

Change-Id: I0d1d94d48779b970bb5d0840c66a14c189ab0091
benjaminp added a commit to benjaminp/bazel that referenced this issue Mar 23, 2018
… to a remote cache.

The remote cache protocol only knows about regular files and
directories. Currently, during action output upload, symlinks are
resolved into regular files. This means cached "executions" of an
action may have different output file types than the original
execution, which can be a footgun. This CL bans symlinks from cachable
spawn outputs and fixes bazelbuild#4840.

The interface of SpawnCache.CacheHandle.store is refactored:
1. The outputs parameter is removed, since that can be retrieved from the underlying Spawn.
2. It can now throw ExecException in order to fail actions.

Change-Id: I0d1d94d48779b970bb5d0840c66a14c189ab0091
@ola-rozenfeld
Copy link
Contributor

Am I understanding correctly that this behavior will need to be changed when https://docs.google.com/document/d/1gnOYszitgrLVet3sQk-TKGqIcpkkDsc6aw-izoo-d64/edit# is implemented?

@benjaminp
Copy link
Collaborator Author

Ah, I wasn't aware of that proposal. Yes, if the remote cache correctly handles symlinks, it shouldn't be necessary to ban them.

@buchgr
Copy link
Contributor

buchgr commented Apr 10, 2018

@ola-rozenfeld is there a time frame for implementing this?

@ola-rozenfeld
Copy link
Contributor

ola-rozenfeld commented Apr 10, 2018 via email

@benjaminp
Copy link
Collaborator Author

Can we reopen this since the change was reverted?

benjaminp added a commit to benjaminp/bazel that referenced this issue Apr 30, 2018
…cache.

This is mostly a roll-forward of 4465dae, which
was reverted by fa36d2f. The main difference is
that the new behavior is now gated behind the --noremote_allow_symlink_upload
flag.

https://docs.google.com/document/d/1gnOYszitgrLVet3sQk-TKGqIcpkkDsc6aw-izoo-d64
is a design proposal to support symlinks in the remote cache, which would render
this change moot. I'd like to be able to prevent incorrect cache behavior until
that change is implemented, though.

This fixes bazelbuild#4840 (again).

Change-Id: I2136cfe82c2e1a8a9f5856e12a37d42cabd0e299
@buchgr buchgr reopened this May 2, 2018
@buchgr
Copy link
Contributor

buchgr commented May 2, 2018

I ll roll the change forward once the no-cache flag has been fixed. Should land sometime next week.

@benjaminp
Copy link
Collaborator Author

I assume you mean the fix for #4343? Can I ask what the new semantics will be?

When preparing #5122, I noticed the roll-forward wasn't clean, so I may need to send a PR anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment