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

Access Denied Error (os error 5) if testing while the main program is running. #12485

Open
EMUNES opened this issue Aug 2, 2023 · 9 comments
Labels
A-diagnostics Area: Error and warning messages generated by Cargo itself. C-bug Category: bug O-windows OS: Windows S-needs-mentor Status: Issue or feature is accepted, but needs a team member to commit to helping and reviewing.

Comments

@EMUNES
Copy link

EMUNES commented Aug 2, 2023

I tried these simple code. But if I run cargo run,and then run cargo test in another terminal, it always shows: error: failed to remove file 'C:\my\Tut\rust_nails\target\debug\rust_nails.exe' Caused by: Access Denied. (os error 5)

main.rs code:

use std::net::SocketAddr;

use axum::response::Html;
use axum::routing::get;
use axum::Router;

#[tokio::main]
async fn main() {
    // The hello world route service.
    let route_hello = Router::new().route(
        "/hello",
        get(|| async { Html("Hello <strong>World!!!</strong>") }),
    ).into_make_service();

    let address = SocketAddr::from(([127, 0, 0, 1], 8000));
    axum::Server::bind(&address)
        .serve(route_hello)
        .await
        .unwrap();
}

Test code:

use anyhow::{Result, Ok};

#[tokio::test]
async fn quick_dev() -> Result<()> {
    let hc = httpc_test::new_client("127.0.0.1:8000").unwrap();

    hc.do_get("/hello").await?.print().await?;

    Ok(())
}

I expected to see this happen: Test should be able to run while the program is running.

Instead, this happened: Testing code failed to execute with OS Error 5.

Meta

rustc --version --verbose:

rustc 1.71.0 (8ede3aae2 2023-07-12)
binary: rustc
commit-hash: 8ede3aae28fe6e4d52b38157d7bfe0d3bceef225
commit-date: 2023-07-12
host: x86_64-pc-windows-msvc
release: 1.71.0
LLVM version: 16.0.5
Backtrace

error: failed to remove file `C:\my\Tut\rust_nails\target\debug\rust_nails.exe`

Caused by:
  Access Denied. (os error 5)

@EMUNES EMUNES added the C-bug Category: bug label Aug 2, 2023
@ChrisDenton

This comment was marked as outdated.

@ehuss ehuss transferred this issue from rust-lang/rust Aug 12, 2023
@ehuss
Copy link
Contributor

ehuss commented Aug 12, 2023

Thanks for the report! I have moved this to the cargo repo.

Unfortunately I'm unable to reproduce with the given instructions. Can you please share a full project that exhibits the problem, including the Cargo.toml and any other parts that are necessary to reproduce it.

@ehuss ehuss added the S-triage Status: This issue is waiting on initial triage. label Aug 12, 2023
@epage
Copy link
Contributor

epage commented Aug 13, 2023

I'm assuming that this is windows specific behavior where you can't overwrite a file that is in use. In this case, so long as the binary from cargo run is still running and cargo test is needing to overwrite that binary, this error will happen.

I'm assuming cargo will only overwrite the main binary if something has changed. Any other operations that are happening might be important when preparing more detailed reproduction steps.

@EMUNES
Copy link
Author

EMUNES commented Aug 13, 2023

Thanks for the report! I have moved this to the cargo repo.

Unfortunately I'm unable to reproduce with the given instructions. Can you please share a full project that exhibits the problem, including the Cargo.toml and any other parts that are necessary to reproduce it.

I can reproduce the problem on win11. The environment is the same as I mentioned in the issue, and here attaches the full code.
demo.zip

@weihanglo
Copy link
Member

I'm assuming that this is windows specific behavior where you can't overwrite a file that is in use.

If this is the case, here are two issues you may be interested in:

@ehuss
Copy link
Contributor

ehuss commented Aug 15, 2023

Looking at the attached project, it looks like the dev-dependencies introduce new features in shared dependencies which cause the binary to be rebuilt. That is tracked in #11954. If you want to avoid those rebuilds, one of the only options is to manually specify the dependencies (with features =["…"] in the dependency) to make sure the normal builds have the same features as the dev builds. You can use cargo tree to determine which features are enabled in the two scenarios, and see what is different.

Another suggestion is to avoid the workflow of having a test expecting to have a server running via cargo run. Usually it is best to have tests launch whichever services they need themselves. That's part of the reason why cargo builds the binary for integration tests, so that they can launch them.

My only suggestion is for cargo to provide a better error message for "Access Denied" when trying to remove an executable, and provide a suggestion to check if the executable is currently running, and explain that it cannot be replaced in that scenario. I can't exactly reproduce the given error here, since on my system the linker fails first with a very different error.

@EMUNES
Copy link
Author

EMUNES commented Aug 18, 2023

Looking at the attached project, it looks like the dev-dependencies introduce new features in shared dependencies which cause the binary to be rebuilt. That is tracked in #11954. If you want to avoid those rebuilds, one of the only options is to manually specify the dependencies (with features =["…"] in the dependency) to make sure the normal builds have the same features as the dev builds. You can use cargo tree to determine which features are enabled in the two scenarios, and see what is different.

Another suggestion is to avoid the workflow of having a test expecting to have a server running via cargo run. Usually it is best to have tests launch whichever services they need themselves. That's part of the reason why cargo builds the binary for integration tests, so that they can launch them.

My only suggestion is for cargo to provide a better error message for "Access Denied" when trying to remove an executable, and provide a suggestion to check if the executable is currently running, and explain that it cannot be replaced in that scenario. I can't exactly reproduce the given error here, since on my system the linker fails first with a very different error.

Thanks! I will try those methods and waiting for better error messages from cargo.

@ehuss ehuss added A-diagnostics Area: Error and warning messages generated by Cargo itself. O-windows OS: Windows S-needs-mentor Status: Issue or feature is accepted, but needs a team member to commit to helping and reviewing. and removed S-triage Status: This issue is waiting on initial triage. labels Nov 22, 2023
@yanlong-li
Copy link

I encountered the same issue. A workaround is to specify a different directory from the default target using the --target-dir parameter, for example --target-dir="target/test", to prevent the conflict.

@dsherret
Copy link

Following up from #14757 (comment) where I suggested killing the process.

Considering we don't know the users intent and people can hit this with "unrelated" commands like cargo run and cargo test, I would be disinclined for us to kill the process.

That makes sense. Maybe it would be nice to prompt for X seconds asking if the user wants to kill the process if it's executing in a tty? It would be a nice quality of life improvement. Running into this can sometimes cost me a few minutes of time if doing a release build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Error and warning messages generated by Cargo itself. C-bug Category: bug O-windows OS: Windows S-needs-mentor Status: Issue or feature is accepted, but needs a team member to commit to helping and reviewing.
Projects
None yet
Development

No branches or pull requests

7 participants