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

Cargo modifies renamed executable in the target directory on rebuild #11101

Closed
Veetaha opened this issue Sep 17, 2022 · 3 comments · Fixed by #11122
Closed

Cargo modifies renamed executable in the target directory on rebuild #11101

Veetaha opened this issue Sep 17, 2022 · 3 comments · Fixed by #11122
Labels
A-layout Area: target output directory layout, naming, and organization C-bug Category: bug O-linux OS: Linux O-windows OS: Windows

Comments

@Veetaha
Copy link

Veetaha commented Sep 17, 2022

Problem

If you rename the executable output file in target/{profile} and rebuild the project, then the renamed file is modified to be a copy of the new binary output.

I suppose it is possible to create an unlimited amount of renamed files this way and all of them will be modified to be the copy of the latest built executable. I've verified that renaming the executable and building the project two times (i.e. having original executable, renamed_copy_1, renamed_copy_2).

Steps

The commands in terminal (bash). I've copied them with the output lower

~/junk $ cargo new rename-repro
     Created binary (application) `rename-repro` package
~/junk $ cd rename-repro
~/junk/rename-repro (master) $ cargo build
   Compiling rename-repro v0.1.0 (/home/veetaha/junk/rename-repro)
    Finished dev [unoptimized + debuginfo] target(s) in 0.39s
~/junk/rename-repro (master) $ ls -lh ./target/debug
total 3.8M
drwxrwxr-x 2 veetaha veetaha 4.0K Sep 17 18:13 build
drwxrwxr-x 2 veetaha veetaha 4.0K Sep 17 18:13 deps
drwxrwxr-x 2 veetaha veetaha 4.0K Sep 17 18:13 examples
drwxrwxr-x 3 veetaha veetaha 4.0K Sep 17 18:13 incremental
-rwxrwxr-x 2 veetaha veetaha 3.8M Sep 17 18:13 rename-repro
-rw-rw-r-- 1 veetaha veetaha  103 Sep 17 18:13 rename-repro.d
~/junk/rename-repro (master) $ mv ./target/debug/rename-repro ./target/debug/renamed-1
~/junk/rename-repro (master) $ echo "static FOO: [u8; 10000000] = [1; 10000000]; fn main() { dbg!(FOO); }" > src/main.rs
~/junk/rename-repro (master) $ cargo build
   Compiling rename-repro v0.1.0 (/home/veetaha/junk/rename-repro)
    Finished dev [unoptimized + debuginfo] target(s) in 0.33s
~/junk/rename-repro (master) $ ls -lh ./target/debug
total 27M
drwxrwxr-x 2 veetaha veetaha 4.0K Sep 17 18:13 build
drwxrwxr-x 2 veetaha veetaha 4.0K Sep 17 18:13 deps
drwxrwxr-x 2 veetaha veetaha 4.0K Sep 17 18:13 examples
drwxrwxr-x 3 veetaha veetaha 4.0K Sep 17 18:13 incremental
-rwxrwxr-x 3 veetaha veetaha  14M Sep 17 18:13 renamed-1
-rwxrwxr-x 3 veetaha veetaha  14M Sep 17 18:13 rename-repro
-rw-rw-r-- 1 veetaha veetaha  103 Sep 17 18:13 rename-repro.d

As you can notice, the size of the file renamed-1 changed to 14M, where it was 3.8M before, and it do is the copy of that latest build (rename-repro)

Here is also the reproduction on windows recorded in a video

rust-rename-repro.mp4

Notes

Verified that the bug reproduces both on Linux amd64 and Windows amd64

Version

cargo 1.63.0 (fd9c4297c 2022-07-01)
release: 1.63.0
commit-hash: fd9c4297ccbee36d39e9a79067edab0b614edb5a
commit-date: 2022-07-01
host: x86_64-unknown-linux-gnu
libgit2: 1.4.2 (sys:0.14.2 vendored)
libcurl: 7.83.1-DEV (sys:0.4.55+curl-7.83.1 vendored ssl:OpenSSL/1.1.1n)
os: Ubuntu 20.04 (focal) [64-bit]
@Veetaha Veetaha added the C-bug Category: bug label Sep 17, 2022
@weihanglo
Copy link
Member

weihanglo commented Sep 17, 2022

Thanks for the report and reproducible steps!

This is not a copy or modification of the renamed executable. Instead, it is a hard link.

drwxrwxr-x 3 veetaha veetaha 4.0K Sep 17 18:13 incremental
-rwxrwxr-x *3* veetaha veetaha  14M Sep 17 18:13 renamed-1
-rwxrwxr-x *3* veetaha veetaha  14M Sep 17 18:13 rename-repro
-rw-rw-r-- 1 veetaha veetaha  103 Sep 17 18:13 rename-repro.d

On Linux, the second column of ls output showing 3 indicates that there are three hard links pointing to the same inode. By design12, Cargo hard links final outputs from target/debug/deps into target/debug on Windows and Linux.

My bold guessing is that the inode was reused so that the renamed hard link and new hard link pointed to the same inode. Unfortunately, it seems that inode reuse depends on multiple things and is not easy to control3. I am not an expert on this topic, though.

BTW my x86_64 Linux did create hard links but cannot reproduce this issue.

Footnotes

  1. https://github.com/rust-lang/cargo/blob/362ce336991a324f5b77cce2f45c5366fc8b6009/src/cargo/core/compiler/mod.rs#L454-L457

  2. https://github.com/rust-lang/cargo/pull/2919

  3. https://stackoverflow.com/questions/51019714

@weihanglo weihanglo added O-windows OS: Windows O-linux OS: Linux A-layout Area: target output directory layout, naming, and organization labels Sep 17, 2022
@weihanglo
Copy link
Member

To confirm my assumption, could you use ls with -i inode flag to check if the inode number remain the same?

@Veetaha
Copy link
Author

Veetaha commented Sep 18, 2022

To confirm my assumption, could you use ls with -i inode flag to check if the inode number remain the same?

Looks like yes

~/junk/rename-repro (master) $ ls -lih ./target/debug/
total 27M
56634295 drwxrwxr-x 2 veetaha veetaha 4.0K Sep 17 18:13 build
56634283 drwxrwxr-x 2 veetaha veetaha 4.0K Sep 17 18:13 deps
56634289 drwxrwxr-x 2 veetaha veetaha 4.0K Sep 17 18:13 examples
56634286 drwxrwxr-x 3 veetaha veetaha 4.0K Sep 17 18:13 incremental
56634359 -rwxrwxr-x 3 veetaha veetaha  14M Sep 17 18:13 renamed-1
56634359 -rwxrwxr-x 3 veetaha veetaha  14M Sep 17 18:13 rename-repro
56634369 -rw-rw-r-- 1 veetaha veetaha  103 Sep 17 18:13 rename-repro.d

Before creating this issue I also thought that there could be something going with hard links, but didn't debug it more thoroughly with ls -i, thanks for the tip! However, I would still create the issue because I think this behavior is very surprising for the users.

My use case, where I found this surprising was the following. I renamed the binary output hoping that I would save a copy of the executable for the future. Then I changed my code and rebuilt the project. Then, imagine how surprised I was to figure out that the executable I renamed before now is the same as the one that I've just rebuilt.

Since this behavior is very magical I propose to either re-review it and maybe make a real copy of the binary instead of hard-linking to target/{profile}/deps. If that's not acceptable we should at least call this out in the documentation and maybe in the rustbook very explicitly (unless it already is 🤔 somewhere, but it's hard to find for me).

By the way, here is a related issue (possibly a duplicate): #8348

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-layout Area: target output directory layout, naming, and organization C-bug Category: bug O-linux OS: Linux O-windows OS: Windows
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants